Creation - - 13/04/2020

Load occurrence dataset

 occurrence_no  record_type    reid_no     collection_no                identified_name    identified_rank identified_no 
 1002162:   1   occ:4678    11942  :   1   52582  :  62   Cetacea indet.        : 280   species    :2525   36652  : 256  
 1002163:   1               11943  :   1   47465  :  52   Mysticeti indet.      : 147   genus      : 726   42971  : 156  
 1002167:   1               12051  :   1   48093  :  42   Odontoceti indet.     : 128   family     : 689   42937  : 128  
 1002169:   1               12057  :   1   75152  :  41   Delphinidae indet.    : 102   suborder   : 287   42953  : 110  
 1002202:   1               12058  :   1   47428  :  29   Balaenopteridae indet.: 101   order      : 285   42977  : 105  
 1002203:   1               (Other): 286   48887  :  27   Balaena mysticetus    :  82   superfamily:  74   64683  :  87  
 (Other):4672               NA's   :4387   (Other):4425   (Other)               :3838   (Other)    :  92   (Other):3836  
                 difference              accepted_name      accepted_rank   accepted_no       early_interval
                      :3757   Cetacea           : 301   species    :2155   36652  : 301   Holocene   : 659  
 recombined as        : 312   Odontoceti        : 242   family     : 804   42937  : 242   Langhian   : 353  
 nomen dubium         : 296   Mysticeti         : 213   genus      : 787   42971  : 213   Burdigalian: 340  
 subjective synonym of: 120   Balaenopteridae   : 169   suborder   : 455   42977  : 169   Zanclean   : 317  
 invalid subgroup of  :  50   Delphinidae       : 113   order      : 301   42953  : 113   Tortonian  : 307  
 corrected to         :  32   Balaena mysticetus:  88   superfamily:  78   64683  :  88   Priabonian : 227  
 (Other)              : 111   (Other)           :3552   (Other)    :  98   (Other):3552   (Other)    :2475  
       late_interval      max_ma            min_ma                    ref_author     ref_pubyr     reference_no       phylum    
              :4128   Min.   : 0.0117   Min.   : 0.000   Uhen              : 230   Min.   :1818   12148  :  98   Chordata:4678  
 Langhian     :  81   1st Qu.: 3.6000   1st Qu.: 2.588   Bianucci et al.   : 122   1st Qu.:1975   24251  :  95                  
 Late Pliocene:  80   Median :11.6200   Median : 5.333   Pilleri           : 122   Median :1998   13672  :  74                  
 Messinian    :  76   Mean   :13.8392   Mean   :10.058   Oishi and Hasegawa: 104   Mean   :1983   19106  :  68                  
 Serravallian :  52   3rd Qu.:20.4400   3rd Qu.:13.820   Fitzgerald        :  98   3rd Qu.:2008   32630  :  61                  
 Tortonian    :  29   Max.   :66.0000   Max.   :47.800   Barnes            :  87   Max.   :2500   12161  :  60                  
 (Other)      : 232                                      (Other)           :3915                  (Other):4222                  
 phylum_no         class       class_no        order       order_no                    family       family_no   
 33815:4678   Mammalia:4678   36651:4678   Cetacea:4678   36652:4678                      : 837          : 837  
                                                                       Delphinidae        : 544   42953  : 544  
                                                                       Balaenopteridae    : 399   42977  : 399  
                                                                       NO_FAMILY_SPECIFIED: 382   NF     : 382  
                                                                       Ziphiidae          : 333   42951  : 333  
                                                                       Basilosauridae     : 279   42936  : 279  
                                                                       (Other)            :1904   (Other):1904  
          genus         genus_no     abund_value            abund_unit        lng                lat        
             :1701          :1701   Min.   :  1.000              :2788   Min.   :-179.983   Min.   :-70.75  
 Balaenoptera: 133   36678  : 133   1st Qu.:  1.000   elements   :   5   1st Qu.: -76.800   1st Qu.: 25.18  
 Balaena     : 116   36676  : 116   Median :  1.000   fragments  :   1   Median :   4.433   Median : 37.08  
 Mesoplodon  : 101   36763  : 101   Mean   :  2.527   individuals:  52   Mean   :  -4.137   Mean   : 26.34  
 Squalodon   :  93   36852  :  93   3rd Qu.:  1.000   specimens  :1832   3rd Qu.:  26.459   3rd Qu.: 45.28  
 Basilosaurus:  81   36681  :  81   Max.   :537.000                      Max.   : 179.533   Max.   : 82.27  
 (Other)     :2453   (Other):2453   NA's   :2786                                                            
                           collection_name collection_subset                             collection_aka       cc      
 Whaling Survey                    : 256   Min.   :   20                                        :3285   US     :1105  
 Lee Creek Mine, Yorktown Formation:  62   1st Qu.:18577     Crag d'Anvers                      :  52   IT     : 380  
 Anvers                            :  52   Median :55621     Felixstowe                         :  43   JP     : 365  
 Felixstow                         :  42   Mean   :39910     Wiegerink, Zwillbrock              :  41   BE     : 241  
 Zwilbroek                         :  41   3rd Qu.:59059     Oberschwaben, Wurttemberg          :  25   NZ     : 167  
 Orciano Pisano                    :  29   Max.   :78523     Fort 4, Mortsel, Oude God, Oude-God:  15   (Other):2419  
 (Other)                           :4196   NA's   :4650      (Other)                            :1217   NA's   :   1  
            state               county                       latlng_basis  latlng_precision            geogscale   
               :1909               :3358                           : 211   seconds:3372                     :3661  
 California    : 271   Calvert     : 108   based on nearby landmark: 197   minutes: 471     basin           :  47  
 Maryland      : 165   Beaufort    :  93   based on political unit : 174   6      : 286     hand sample     :  13  
 Antwerpen     : 158   Westmoreland:  80   estimated from map      :3104   1      : 122     local area      : 388  
 Virginia      : 141   San Diego   :  60   stated in text          : 947   5      : 107     outcrop         : 469  
 North Carolina: 130   Suffolk     :  52   unpublished field data  :  45   3      : 103     small collection: 100  
 (Other)       :1904   (Other)     : 927                                   (Other): 217                            
  paleomodel      paleolng           paleolat                                             geoplate         cc.1      protected 
       : 215   Min.   :-178.760   Min.   :-70.75   109                                        : 651   US     :1064      :4586  
 gp_mid:4463   1st Qu.: -69.820   1st Qu.: 18.98   315                                        : 537   IT     : 379   FED:  78  
               Median :   5.560   Median : 38.41   coordinates not computable using this model: 399   JP     : 361   NPS:  14  
               Mean   :  -3.457   Mean   : 25.77   307                                        : 360          : 247             
               3rd Qu.:  22.328   3rd Qu.: 44.53   610                                        : 335   BE     : 238             
               Max.   : 179.610   Max.   : 82.27                                              : 215   (Other):2388             
               NA's   :614        NA's   :614      (Other)                                    :2181   NA's   :   1             
    formation         stratgroup               member             stratscale            zone            localsection 
         :2219             :4056                  :3823                :3062              :4516               :4584  
 Calvert : 240   Chesapeake: 365   Plum Point     : 127   bed          : 250   MPL4b/MPL5a:  34   Pisco       :  39  
 Pisco   :  85   Jackson   :  58   Calvert Beach  :  79   formation    : 604   N18-N19    :  12   Krkwd       :  11  
 Yorktown:  81   Hawthorn  :  42   Eibergen       :  43   group        :  21   MN 17      :   9   SDgFm       :   7  
 Berchem :  48   Cooper    :  17   Bone Valley    :  42   group of beds: 324   MN 3       :   8   Fan Delta   :   4  
 Red Crag:  48   Ashiya    :  15   Antwerpen Sands:  34   member       : 417   MN 14      :   7   Langebaanweg:   4  
 (Other) :1957   (Other)   : 125   (Other)        : 530                        (Other)    :  92   (Other)     :  29  
    localbed                  localorder        regionalsection    regionalbed         regionalorder 
        :4593                      :4594                :4434            :4439                :4441  
 2      :  17   bottom to top      :  39   Blankenhorn  :   2   14       :  45   bottom to top: 237  
 AGL    :  14   no particular order:  43   Panama Canal :   1   12       :  36                       
 SAO    :  12   top to bottom      :   2   Santa Barbara:   1   10       :  20                       
 1      :   7                              Shattuck     : 237   13       :  16                       
 MTM    :   7                              Siwa Oasis   :   1   d\x8ec-13:  15                       
 (Other):  28                              Waihao River :   2   (Other)  : 107                       
                                                                                                                                                                                                                                                                                                                                                                                                                                         lithdescript 
                                                                                                                                                                                                                                                                                                                                                                                                                                               :3701  
 bluish clayey sand\\r\\n"The Yorktown Formation at Lee Creek... is generally a very muddy quartz sand... shell material and cemented sediment comprise less than 3 percent of\\r\\nmost samples" although there is a "boulder bed" at the top of the formation and a single zone of "extensively leached, partially indurated zone that contains abundant molds of turritellid gastropods and cemented clumps of sediment (Snyder et al. 1983):  62  
 shelf mudstone                                                                                                                                                                                                                                                                                                                                                                                                                                :  49  
 no lithological description given                                                                                                                                                                                                                                                                                                                                                                                                             :  41  
 upper marine molasse                                                                                                                                                                                                                                                                                                                                                                                                                          :  25  
 brownish sandy clay                                                                                                                                                                                                                                                                                                                                                                                                                           :  24  
 (Other)                                                                                                                                                                                                                                                                                                                                                                                                                                       : 776  
        lithology1           lithadj1             lithification1           minor_lithology1 fossilsfrom1        lithology2  
 not reported:1628               :3853                   :4320                     :4238     :2706                   :4473  
             : 904   blue        : 119   lithified       :  88   sandy             : 171    Y:1972       sandstone   :  68  
 sandstone   : 888   glauconitic :  75   poorly lithified:  95   argillaceous,muddy:  62                 siltstone   :  62  
 claystone   : 340   diatomaceous:  52   unlithified     : 175   silty             :  56                 "limestone" :  17  
 "limestone" : 186   phosphatic  :  40                           argillaceous      :  48                 conglomerate:  14  
 siltstone   : 157   brown       :  32                           calcareous        :  42                 "shale"     :  12  
 (Other)     : 575   (Other)     : 507                           (Other)           :  61                 (Other)     :  32  
                              lithadj2             lithification2                minor_lithology2 fossilsfrom2
                                  :4620                   :4647                          :4659     :4617      
 tuffaceous,gray                  :  15   lithified       :  11   calcareous             :   2    Y:  61      
 yellow                           :  14   poorly lithified:  11   calcareous,carbonaceous:   5                
 black,brown                      :   5   unlithified     :   9   sandy                  :   7                
 fine                             :   5                           silty                  :   2                
 lenticular,"cross stratification":   2                           silty,sandy            :   3                
 (Other)                          :  17                                                                       
         environment           tectonic_setting                               assembl_comps  articulated_parts associated_parts
 marine indet. :2005                   :4630                                         :1269       :4583             :4623       
               : 596   cratonic basin  :   7    macrofossils                         :3220   many:  14         many:   5       
 coastal indet.: 515   foreland basin  :   7    macrofossils,mesofossils             :  69   none:  62         none:  11       
 estuary/bay   : 208   passive margin  :  32    macrofossils,mesofossils,microfossils: 101   some:  19         some:  39       
 foreshore     : 131   pull-apart basin:   2    macrofossils,microfossils            :  12                                     
 offshore shelf: 124                            mesofossils                          :   4                                     
 (Other)       :1099                            mesofossils,microfossils             :   3                                     
                                                    common_body_parts rare_body_parts            feed_pred_traces
                                                             :4659          :4674                        :4634   
 partial skeletons,teeth,vertebrae,limb elements,plant debris:   4    valves:   4     drill holes        :   1   
 partial skeletons                                           :   3                    gastric dissolution:   4   
 mandibles                                                   :   2                    tooth marks        :  39   
 partial skulls                                              :   2                                               
 shells                                                      :   2                                               
 (Other)                                                     :   6                                               
                                                        artifacts                                    pres_mode   
                                                             :4657   body                                 :1810  
 stone points,stone tools                                    :   8   body,original phosphate              :1446  
 stone points,stone tools,bone tools,textiles                :   6                                        :1254  
 stone tools,ceramics,structural remains,historical artifacts:   2   body,original phosphate,anthropogenic:  26  
 charcoal/hearths                                            :   1   body,anthropogenic                   :  25  
 historical artifacts                                        :   1   body,soft parts,original phosphate   :  18  
 (Other)                                                     :   3   (Other)                              :  99  
 preservation_quality        spatial_resolution    temporal_resolution       lagerstatten    concentration         orientation  
          :4424                       :4647                  :4651                 :4672            :4675                :4669  
 excellent:  89       allochthonous   :   3     condensed    :   1     conservation:   6   #NOM?    :   2   life position:   1  
 good     :  92       autochthonous   :  20     snapshot     :   9                         dispersed:   1   preferred    :   6  
 medium   :  42       parautochthonous:   8     time-averaged:  17                                          random       :   2  
 poor     :  17                                                                                                                 
 variable :  14                                                                                                                 
                                                                                                                                
 abund_in_sediment    fragmentation       bioerosion       encrustation               collection_type
         :4645               :4661             :4675             :4674                        : 750  
 abundant:   6     frequent  :   7   none      :   1   frequent  :   2   archaeological       :  70  
 common  :  22     occasional:  10   occasional:   2   occasional:   2   biostratigraphic     :  55  
 rare    :   5                                                           general faunal/floral:2656  
                                                                         paleoecologic        :  25  
                                                                         taphonomic           :  38  
                                                                         taxonomic            :1084  
                                          collection_methods       museum                              collection_coverage
                                                   :3911              :4447                                      :4501    
 surface (in situ),field collection                : 157     UCMP     :  69   some genera                        :  45    
 field collection                                  : 138     USNM     :  53   some macrofossils                  :  40    
 bulk,salvage,surface (float),sieve                :  62     LACM     :  49   some macrofossils,some microfossils:  20    
 surface (float),surface (in situ),field collection:  53     LACM,UCMP:   8   some microfossils                  :  16    
 surface (float),field collection                  :  38     FLMNH    :   7   all macrofossils,some genera       :  14    
 (Other)                                           : 319     (Other)  :  45   (Other)                            :  42    
      collection_size rock_censused                                       collectors        collection_dates
              :4603          :4674                                             :4642                :4661   
 1 specimens  :  36   2000 kg:   3   Bowman                                    :   6   2014-2016    :   5   
 0            :  11   5 kg   :   1   Dubalen                                   :   5   December 1998:   3   
 1 individuals:   6                  H. Lodge                                  :   4   1899         :   1   
 185 specimens:   3                  Fordyce, Rust, A. Grebneff, and S. Wilson,:   3   1969         :   1   
 2 specimens  :   3                  Marasti                                   :   2   1987         :   1   
 (Other)      :  16                  (Other)                                   :  16   (Other)      :   6   
              taxon_environment            motility                        life_habit                             diet     
                       : 774                   : 774                            :3424                               : 774  
 freshwater            :  17    actively mobile:3904   amphibious, depth=surface:   5   carnivore                   :1604  
 freshwater,terrestrial:   5                           aquatic                  : 666   carnivore, suspension feeder: 593  
 marine                :1749                           aquatic, depth=surface   : 583   piscivore                   : 221  
 marine,freshwater     :2067                                                            piscivore, carnivore        : 903  
 oceanic               :  66                                                            suspension feeder           : 583  
                                                                                                                           
     reproduction                   ontogeny            composition  
           : 774                        : 774                 : 774  
 viviparous:3904   modification of parts:3904   hydroxyapatite:3899  
                                                phosphatic    :   5  
                                                                     
                                                                     
                                                                     
                                                                     

Reorder accepted ranks according to classification standard.

 [1] "family"         "genus"          "infraorder"     "order"          "species"        "subfamily"      "suborder"      
 [8] "subspecies"     "superfamily"    "unranked clade"

Load the list of occurrences with morphological information

                      Taxon    composite..n.y.     occ.data.based.on        Specimen  pbdb_specimen_no pbdb_occurence.number
 Aetiocetus_cotylalveus  : 1   Min.   :0.0000               :60      AMNH 9485  : 1   Min.   : 25492   Min.   :  68135      
 Agorophius_pygmaeus     : 1   1st Qu.:0.0000   CMM-V-15    : 1      CASG 66660 : 1   1st Qu.: 25706   1st Qu.: 461107      
 Albertocetus_meffordorum: 1   Median :0.0000   MGGC 8548   : 1      CCNHM-101  : 1   Median : 25922   Median : 487310      
 Albireo_whistleri       : 1   Mean   :0.3768   MNHN SAS 933: 1      ChM PV4256 : 1   Mean   : 35167   Mean   : 631596      
 Archaeodelphis_patrius  : 1   3rd Qu.:1.0000   UCMP 83790  : 1      ChM PV4844 : 1   3rd Qu.: 26035   3rd Qu.: 763082      
 Ashleycetus_planicapitis: 1   Max.   :1.0000   USNM 10484  : 1      CHM_PV_4253: 1   Max.   :146940   Max.   :1360382      
 (Other)                 :63                    (Other)     : 4      (Other)    :63   NA's   :56                            
                                                                                                                                                                             notes   
                                                                                                                                                                                :62  
 actually this info relates to the holotype, which is MGGC 8608, but it seems that MGGC 8599 has not been entered                                                               : 1  
 It is unclear which specimen is in the pbdb, both are from the Pisco Formation. This one is the referred specimen, not the holotype (but ir is more complete than the holotype): 1  
 two specimen numbers in pbdb, but both relate to same specimen                                                                                                                 : 1  
 two specimens in database, but one comes from USA, so I selected the one from Peru based on collection info                                                                    : 1  
 two specimens in pbdb, unlcear which is which because they belong to the same horizon                                                                                          : 1  
 (Other)                                                                                                                                                                        : 2  

Combine those taxa with extant taxa to get all the species included in the tree.

                        taxon         min         max   
 Balaena_mysticetus        : 1   Min.   :0   Min.   :0  
 Balaenoptera_acutorostrata: 1   1st Qu.:0   1st Qu.:0  
 Balaenoptera_bonaerensis  : 1   Median :0   Median :0  
 Balaenoptera_borealis     : 1   Mean   :0   Mean   :0  
 Balaenoptera_brydei       : 1   3rd Qu.:0   3rd Qu.:0  
 Balaenoptera_edeni        : 1   Max.   :0   Max.   :0  
 (Other)                   :82                          
                      taxon         min              max       
 Aetiocetus_cotylalveus  : 1   Min.   : 2.588   Min.   : 3.60  
 Agorophius_pygmaeus     : 1   1st Qu.: 7.246   1st Qu.:11.62  
 Albertocetus_meffordorum: 1   Median :13.820   Median :15.97  
 Albireo_whistleri       : 1   Mean   :14.357   Mean   :18.28  
 Archaeodelphis_patrius  : 1   3rd Qu.:23.030   3rd Qu.:28.10  
 Ashleycetus_planicapitis: 1   Max.   :41.300   Max.   :47.80  
 (Other)                 :63                                   
                        taxon          min             max        
 Balaena_mysticetus        :  1   Min.   : 0.00   Min.   : 0.000  
 Balaenoptera_acutorostrata:  1   1st Qu.: 0.00   1st Qu.: 0.000  
 Balaenoptera_bonaerensis  :  1   Median : 0.00   Median : 0.000  
 Balaenoptera_borealis     :  1   Mean   : 6.31   Mean   : 8.035  
 Balaenoptera_brydei       :  1   3rd Qu.:11.62   3rd Qu.:13.820  
 Balaenoptera_edeni        :  1   Max.   :41.30   Max.   :47.800  
 (Other)                   :151                                   

Check that the names in the datasets are exactly the same as in the list above.

[1] TRUE

Idem at the generic level for the genus analysis.

                        taxon         min         max   
 Balaena_mysticetus        : 1   Min.   :0   Min.   :0  
 Balaenoptera_physalus     : 1   1st Qu.:0   1st Qu.:0  
 Berardius_bairdii         : 1   Median :0   Median :0  
 Caperea_marginata         : 1   Mean   :0   Mean   :0  
 Cephalorhynchus_heavisidii: 1   3rd Qu.:0   3rd Qu.:0  
 Delphinapterus_leucas     : 1   Max.   :0   Max.   :0  
 (Other)                   :35                          
                      taxon         min              max       
 Aetiocetus_cotylalveus  : 1   Min.   : 2.588   Min.   : 3.60  
 Agorophius_pygmaeus     : 1   1st Qu.: 7.246   1st Qu.:11.62  
 Albertocetus_meffordorum: 1   Median :13.820   Median :15.97  
 Albireo_whistleri       : 1   Mean   :14.960   Mean   :18.95  
 Archaeodelphis_patrius  : 1   3rd Qu.:23.030   3rd Qu.:28.10  
 Ashleycetus_planicapitis: 1   Max.   :41.300   Max.   :47.80  
 (Other)                 :56                                   
                        taxon         min              max        
 Balaena_mysticetus        : 1   Min.   : 0.000   Min.   : 0.000  
 Balaenoptera_physalus     : 1   1st Qu.: 0.000   1st Qu.: 0.000  
 Berardius_bairdii         : 1   Median : 5.333   Median : 7.246  
 Caperea_marginata         : 1   Mean   : 9.005   Mean   :11.409  
 Cephalorhynchus_heavisidii: 1   3rd Qu.:15.970   3rd Qu.:20.440  
 Delphinapterus_leucas     : 1   Max.   :41.300   Max.   :47.800  
 (Other)                   :97                                    

Check that the names in the datasets are exactly the same as in the list above.

[1] TRUE

Remove those occurrences from our initial dataset to avoid redundancy.

Explore the dataset

Repartition through time

Full fossil record

\(\to\) Numerous occurrences seem to have the same age interval so in order to avoid clusters let’s draw them uniformly in their stratigraphic range rather than taking the mean.

\(\to\) The repartition seems much smoother now.

Subsampling

These occurrences are too numerous for our current implementation, let’s subsample a fraction of them for now.

\(\to\) The distribution looks similar, with some noise due to higher variance with smaller sample.

Repartition among accepted ranks

Pie chart

\(\to\) Half of the occurrences are identified at the level of the secies and 1/3 at the genus or family.

Some clades are unranked :


  Chaeomysticeti          Neoceti Panphyseteroidea       Pelagiceti  Platanidelphidi       Squaloceti 
              26                2                1                1                1                1 

Time repartition by rank

\(\to\) Apparent huge cluster of occurrences in recent times, with very precise dating = Artefact due to the “Pull of the Recent” effect ? \(\to\) We decided to remove all Late Pleistocene and Holocene occurrences (thus setting the \(\omega\)-sampling to 0) in order to avoid this bias.

\(\to\) We observe similar trends at each rank, with peaks at ~15My and ~5My.

Redundancy of occurrences with the same accepted name

\(\to\) ~Half of species/genera/subfamilies have only one specimen by accepted name, but it could go up to ~50 within the same species and ~200 occurrences within the same suborder. Those differences will have to be corrected because in our model all species are upposed to have the same abundance (identical sampling rates among branches).

\(\implies\) Our goal now will be to correct this abundance bias.

Time intervals = stratigraphic age uncertainty

Minimum and maximum stratigraphic limits

\(\to\) Most species have a early but not a late stratigraphic limit.

Minimum and maximum ages

Time ranges = duration of the time intervals

Count occurrences by accepted name

\(\to\) Some occurrences have too much age uncertainty, they risk to artificially increase species durations.

Remove occurrences with highly uncertain dating (range > 10My)

[1] 3505  117

Most of occurrences show less than 10 My age uncertainty, let’s try to keep only these ones.

\(\to\) The removal of highly uncertain occurrences seems to be only a little biased, even if uncertainty globally increases with age.

\(\to\) Some species (or other ranks) have several occurrences with several time ranges, let’s combine them into a unique range covering all the others.

Combined time ranges = unique time range for occurrences with the same name (without the biggest ones)

Occurrence density

Density distributions

\(\to\) Density logically increases as taxa ranks increase.

Correlation between time range and age

If we want to correct species abundance differences based on the number of occurrences in the time range (“density”), those factors should not depend on time in order to avoid penalizing periods with higher densities.

\(\to\) It seems that age range varies importantly with time, but when taking the full combined range into account the correlation seems quite weak after the first million years.

Let’s look at the density directly, because this is what is interesting us directly.

\(\to\) The density based on combined ranges is much less time-dependant than the density based on initial range ages. We will therefore use the combined density for our corrections.

Sub-sampling of occurrences with a normalized density along the combined ranges

Compare densities for single vs. combined ranges.

\(\to\) Densities are smaller and more concentrated with the combined ranges (larger time span + less ranges in total because of the collepses into unique ranges).

Compare densities by accepted name count (species only)

Let’s focus now on the occurrences accepted at the species level because they are the one for which we can correct the abundance bias by subsampling the most concentrated combined intervals.

\(\to\) Their is a huge span of densities driven by the number of occurrences for the same species that we can reduce by subsampling the most concentrated intervals.

Impact of correcting subsampling on density distributions (species only)

\(\to\) Subsampling successfully reduces the density span from 2 to 1 order of magnitude.

Impact of subsampling on occurrences repartition (species only)

See what our distributions loook like after subsampling :

\(\to\) Some highly dense cluster became much more similar to the others.

If we superpose these 2 plots :

\(\to\) We get the new species occurrence repartition after subsampling correction, that could be used for doing inference with the occurrence birth-death model.

New developments

Compare with a Poisson sampling process

In order to check if the data fit our assumptions of constant-fossilisation-rate Poisson sampling we compare the observed occurrences distributions with the expected ones. Specifically, we will look at the number of taxa represented by 1, 2, 3, … occurrences and the one that we would expect for a given distribution of combined age ranges (as a proxy for species duration).

In a Poisson process with occurrence sampling rate \(\omega\) and for a given time interval of length \(t\), the probability of observing \(N_t = k\) occurrences is given by the Poisson distribution of mean of parameter \(\omega\times t\) :

\[\mathbb{P}(N_t=k) = e^{-\omega t}\frac{(\omega t)^k}{k!}\]

So in order to have the absolute probability of observing \(N_0 = n\) occurrences we have to integrate over the full distribution of age ranges \(t\), called \(f(t)\) :

\[\mathbb{P}(N_0 = n) = \int_t P(N_t = n) f(t) dt = \int_t e^{-\omega t}\frac{(\omega t)^n}{n!} f(t) dt\]

First, approximate this distribution :

Then integrate and plot the expected distribution for a given omega :

Finally, try to find an \(\omega\) value that approximately fits the first points (the least affected by oversampling biases) and check if the other points follow the expected curve :

\(\implies\) Initial observations really do not fit the expectations, species with more than 5 occurrences must remain very rare ! But our subsampling seems to correct most of this bias.

However, this method requires to make several arbitrary choices that may introduce new biases so we will instead subsample at other levels (palaeontological collection, geological formation). In each case only one occurrence will be sampled for the similarly identified, a process we will refer to as aggregating these occurrences according to the chosen factor.

Aggregate similarly identified occurrences in each collection

\(\to\) Each collection corresponds to a unique time interval (inferred from the unique age mean).

In order to reduce the abundance bias, we may keep only one occurrence for each collection :

\(\to\) Not enough occurrences are removed to make a sufficient difference. If we look at the collection with the highest number of occurrences :


        Aprixokogia kelloggi                      Balaena   Balaenoptera acutorostrata              Balaenopteridae 
                           1                            2                            2                            2 
                   Balaenula      Bohaskaia monodontoides                Cetotheriinae               Delphinapterus 
                           2                            1                            1                            3 
                 Delphinidae                    Delphinus                 Globicephala          Gricetoides aurorae 
                           2                            2                            2                            1 
              Herpetocetinae       Herpetocetus sendaicus Herpetocetus transatlanticus              Kogia breviceps 
                           1                            1                            1                            1 
                    Kogiidae                     Kogiinae          Kogiopsis floridana               Lagenorhynchus 
                           1                            2                            1                            2 
    Lagenorhynchus harmatuki                    Megaptera      Mesoplodon longirostris                      Monodon 
                           1                            2                            2                            1 
    Ninoziphius platyrostris                Orycterocetus       Physeter macrocephalus                 Physeteridae 
                           3                            1                            1                            1 
                Physeterinae           Physeterula dubusi                  Plesiocetus        Pliopontos littoralis 
                           2                            1                            1                            1 
                  Pontoporia                Pontoporiidae                    Pseudorca                  Scaldicetus 
                           1                            2                            2                            1 
                    Stenella                Stenella rayi                     Tursiops          Ziphius cavirostris 
                           2                            1                            2                            2 

\(\to\) There are very few redundancies among the accepted names in collections so aggregating those won’t reduce the abundance bias.

Instead, we may try to aggregate occurrences with the same accepted name at the level of the geological formation (ie subsample only one for each).

Aggregate similarly identified occurrences in each formation

\(\to\) For most formations each species seems to be restricted to only one age, so as expected we are not loosing too much information when aggregating them to a single occurrence.

\(\to\) In that case the sub-sampling is big enough to hope correcting our bias.

\(\to\) The bias can be corridered as completely corrected.

Removed 2 rows containing missing values (geom_bar).

Removed 2 rows containing missing values (geom_bar).

Removed 2 rows containing missing values (geom_bar).Removed 2 rows containing missing values (geom_bar).

\(\to\) Comparing with the initial occurrences distribution and with the distribution after our first sub-sampling it appears that both methods lead to very similar distributions. This conforts us about the robustness of those approaches.

However, we have to take into account the occurrences that do not have any indicated geological formation to subsample them separately. To approximate geological formation we chose to proceed to the aggregation based on the combination of the country and the early stratigraphic interval.

Aggregate occurrences without formation by country + early interval

More occurrences remain after aggregating with this new method. Let’s compare again with the theoretical distribution :

\(\to\) The correspondance is still good, except for two taxa :


   Scaldicetus grandis Schizodelphis sulcatus 
                    14                     16 

Removed 2 rows containing missing values (geom_bar).

Removed 2 rows containing missing values (geom_bar).

Removed 2 rows containing missing values (geom_bar).Removed 2 rows containing missing values (geom_bar).

\(\to\) Comparing with the initial occurrences distribution and with the distribution after our first sub-sampling it appears that both methods lead to very similar distributions. This conforts us about the robustness of those approaches.

Replacing coutries by gelogical plates seems to make more sens from a palaeontological perspective, so let’s try it.

Aggregate occurrences without formation by geoplate + early interval

More occurrences remain after aggregating with this new method. Let’s compare again with the theoretical distribution :

\(\to\) The correspondance is still good, except for two taxa :


   Scaldicetus grandis Schizodelphis sulcatus 
                    13                     15 
Removed 2 rows containing missing values (geom_bar).

Removed 2 rows containing missing values (geom_bar).

Removed 2 rows containing missing values (geom_bar).Removed 2 rows containing missing values (geom_bar).

\(\to\) Delimiting by geological plates (+ age) instead of countries (+ age) leads to similar distributions, so we will keep it.

Check that the sampling methods do not introduce biases in the repartition between Odontoceti and Mysticeti

Mystecetes are usually larger than odontocetes, and size is associated with a wider geographic range so since we are subsampling occurrences according to geological formation we may be biasing our data towards more widespread species, therefore towards mystecetes.

Look at the families first :

\(\to\) The family repartitions vary a bit after subsampling, but because of the limited number of species by family the fact that we corrected the oversampling of some species could have a disproportionate effect.

Let’s look rather at a higher taxonomic rank, by importing the topology of cetacean families (from Marx et al. 2016) :

`data_frame()` is deprecated as of tibble 1.1.0.
Please use `tibble()` instead.
This warning is displayed once every 8 hours.
Call `lifecycle::last_warnings()` to see where this warning was generated.

\(\to\) There is a smaller proportion of archeocete occurrences after either sampling, because a huge cluster is subsampled around 35 My ago, but this effect is expected. However, for the Mysticeti vs. Odotoceti there is no huge apparent bias, especially with the aggregating method.

Faster genus-level analysis

More occurrences remain after aggregating with this new method. Let’s compare again with the theoretical distribution :

\(\to\) The correspondance is much less improved than with species aggregation because some genera have a lot of occurrences due to their high number of species species :


Balaenoptera   Kentriodon   Mesoplodon  Scaldicetus    Squalodon 
          53           27           30           41           40 
Removed 2 rows containing missing values (geom_bar).

Removed 2 rows containing missing values (geom_bar).

Removed 2 rows containing missing values (geom_bar).Removed 2 rows containing missing values (geom_bar).

\(\to\) Delimiting by geological plates (+ age) instead of countries (+ age) leads to similar distributions, with a bit more occurrences, so we will keep it.

Conclusions

Achievements :

Open questions :

LS0tCnRpdGxlOiAiRm9ybWF0IENldGFjZWFucyBEYXRhIgpvdXRwdXQ6CiAgcGRmX2RvY3VtZW50OiAKICAgIGZpZ19oZWlnaHQ6IDUuNQogICAgZmlnX3dpZHRoOiAxMAogICAgdG9jOiB5ZXMKICBodG1sX25vdGVib29rOgogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgaHRtbF9kb2N1bWVudDoKICAgIGZpZ193aWR0aDogMTAKICAgIHRvYzogeWVzCi0tLQoKQ3JlYXRpb24gLSBqZXJlbXkuYW5kcmVvbGV0dGlAZW5zLmZyIC0gMTMvMDQvMjAyMAoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gRkFMU0UpCmBgYAoKYGBge3IgaW5jbHVkZT1GQUxTRX0KbGlicmFyeSgiZ2dwbG90MiIpCmxpYnJhcnkoImRwbHlyIikKbGlicmFyeSgiZ2d0cmVlIikKYGBgCgojIExvYWQgb2NjdXJyZW5jZSBkYXRhc2V0CgpgYGB7cn0KIyBzZXR3ZCgifi9Eb2N1bWVudHMvU2NvbGFpcmUvRU5TL1N0YWdlX00xL0NldGFjZWFucy8iKQojIGNldGFjZWFfcGJkYiA8LSByZWFkLmNzdigiZGF0YS1jZXRhY2VhbnMvY2V0YWNlYV9wYmRiXzA1X0Fwcl8yMDE4LmNzdiIsIHNraXAgPSAxNikKY2V0YWNlYV9wYmRiIDwtIHJlYWQuY3N2MigiZGF0YS1jZXRhY2VhbnMvY2V0YWNlYV9wYmRiXzExX01heV8yMDIwLmNzdiIsIHNraXAgPSAxNykKIyBSZW1vdmUgY29sdW1ucyB3aXRoIG9ubHkgTkFzCmNldGFjZWFfcGJkYiA8LSBjZXRhY2VhX3BiZGJbLGNvbFN1bXMoaXMubmEoY2V0YWNlYV9wYmRiKSkgPCBucm93KGNldGFjZWFfcGJkYildCiMgUmVjb3JkIGNsYXNzeWluZyBudW1iZXJzIGFzIGZhY3RvcnMKY2V0YWNlYV9wYmRiWywgZ3JlcCgiX25vIiwgbmFtZXMoY2V0YWNlYV9wYmRiKSwgdmFsdWUgPSBUKV0gPC0gZGF0YS5mcmFtZShzYXBwbHkoY2V0YWNlYV9wYmRiWywgZ3JlcCgiX25vIiwgbmFtZXMoY2V0YWNlYV9wYmRiKSwgdmFsdWUgPSBUKV0sIGFzLmZhY3RvcikpCiMgUmVjb3JkIG51bWVyaWMgcXVhbnRpdGllcyBhcyBkb3VibGVzCmNldGFjZWFfcGJkYlssIGMoImxhdCIsICJsbmciLCAicGFsZW9sYXQiLCAicGFsZW9sbmciLCAibWluX21hIiwgIm1heF9tYSIpXSA8LSBzYXBwbHkoY2V0YWNlYV9wYmRiWywgYygibGF0IiwgImxuZyIsICJwYWxlb2xhdCIsICJwYWxlb2xuZyIsICJtaW5fbWEiLCAibWF4X21hIildLCBmdW5jdGlvbihjb2wpe2FzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGNvbCkpfSkKc3VtbWFyeShjZXRhY2VhX3BiZGJbZ3JlcCgiY29tbWVudCIsIG5hbWVzKGNldGFjZWFfcGJkYiksIHZhbHVlID0gVCwgaW52ZXJ0PVQpXSkKYGBgCgpgYGB7cn0KaGVhZChjZXRhY2VhX3BiZGIsIDEwKQpgYGAKClJlb3JkZXIgYWNjZXB0ZWQgcmFua3MgYWNjb3JkaW5nIHRvIGNsYXNzaWZpY2F0aW9uIHN0YW5kYXJkLgoKYGBge3J9CmxldmVscyhjZXRhY2VhX3BiZGIkYWNjZXB0ZWRfcmFuaykKY2V0YWNlYV9wYmRiJGFjY2VwdGVkX3JhbmsgPC0gZmFjdG9yKGNldGFjZWFfcGJkYiRhY2NlcHRlZF9yYW5rLCBsZXZlbHM9Yygic3Vic3BlY2llcyIsICJzcGVjaWVzIiwgImdlbnVzIiwgInN1YmZhbWlseSIsICJmYW1pbHkiLCAic3VwZXJmYW1pbHkiLCAiaW5mcmFvcmRlciIsICJzdWJvcmRlciIsICJvcmRlciIsICJ1bnJhbmtlZCBjbGFkZSIpKQpjZXRhY2VhX3BiZGIkaWRlbnRpZmllZF9yYW5rIDwtIGZhY3RvcihjZXRhY2VhX3BiZGIkaWRlbnRpZmllZF9yYW5rLCBsZXZlbHM9Yygic3Vic3BlY2llcyIsICJzcGVjaWVzIiwgImdlbnVzIiwgInN1YmZhbWlseSIsICJmYW1pbHkiLCAic3VwZXJmYW1pbHkiLCAiaW5mcmFvcmRlciIsICJzdWJvcmRlciIsICJvcmRlciIsICJ1bnJhbmtlZCBjbGFkZSIpKQpgYGAKCiMgTG9hZCB0aGUgbGlzdCBvZiBvY2N1cnJlbmNlcyB3aXRoIG1vcnBob2xvZ2ljYWwgaW5mb3JtYXRpb24KCmBgYHtyfQpvY2N1cnJlbmNlc193aXRoX21vcnBob2xvZ3kgPC0gcmVhZC5jc3YyKCJkYXRhLWNldGFjZWFucy9TcGVjaW1lbnNQQkRCX25ld05hbWVzLmNzdiIpCnN1bW1hcnkob2NjdXJyZW5jZXNfd2l0aF9tb3JwaG9sb2d5KQpgYGAKCkNvbWJpbmUgdGhvc2UgdGF4YSB3aXRoIGV4dGFudCB0YXhhIHRvIGdldCBhbGwgdGhlIHNwZWNpZXMgaW5jbHVkZWQgaW4gdGhlIHRyZWUuCgpgYGB7cn0KZXh0YW50X3RheGEgPC0gcmVhZC5jc3YyKCJkYXRhLWNldGFjZWFucy9DZXRhY2VhX2V4dGFudF90YXhhLmNzdiIpCnN1bW1hcnkoZXh0YW50X3RheGEpCmBgYAoKYGBge3J9CmV4dGluY3RfdGF4YSA8LSBjZXRhY2VhX3BiZGJbY2V0YWNlYV9wYmRiJG9jY3VycmVuY2Vfbm8gJWluJSBvY2N1cnJlbmNlc193aXRoX21vcnBob2xvZ3kkcGJkYl9vY2N1cmVuY2UubnVtYmVyLCBjKCJhY2NlcHRlZF9uYW1lIiwgIm1pbl9tYSIsICJtYXhfbWEiKV0KZXh0aW5jdF90YXhhJGFjY2VwdGVkX25hbWUgPC0gYXMuZmFjdG9yKGdzdWIoIiAiLCAiXyIsIGV4dGluY3RfdGF4YSRhY2NlcHRlZF9uYW1lKSkKbmFtZXMoZXh0aW5jdF90YXhhKSA8LSBuYW1lcyhleHRhbnRfdGF4YSkKc3VtbWFyeShleHRpbmN0X3RheGEpCmBgYAoKYGBge3J9CnRheGEgPC0gcmJpbmQoZXh0YW50X3RheGEsIGV4dGluY3RfdGF4YSkKc3VtbWFyeSh0YXhhKQp3cml0ZS50YWJsZSh0YXhhLCBmaWxlID0gImRhdGEtY2V0YWNlYW5zL0NldGFjZWFfdGF4YS5jc3YiLCBxdW90ZSA9IEYsIHNlcD0iXHQiLCByb3cubmFtZXMgPSBGKQpgYGAKCkNoZWNrIHRoYXQgdGhlIG5hbWVzIGluIHRoZSBkYXRhc2V0cyBhcmUgZXhhY3RseSB0aGUgc2FtZSBhcyBpbiB0aGUgbGlzdCBhYm92ZS4KCmBgYHtyfQptb3JwaG9fbmFtZXMgPC0gcmVhZC50YWJsZSgiZGF0YS1jZXRhY2VhbnMvbW9ycGhvX3NpbXBsaWZpZWRfbmV3TmFtZXNfcmVtb3ZlT3V0Z3JvdXBzVW5kZXNjcmliZWQubmV4Iiwgc2tpcD02LCBmaWxsPVQpCm1vcnBob19uYW1lcyA8LSBkcm9wbGV2ZWxzKG1vcnBob19uYW1lcyRWMVtzYXBwbHkobW9ycGhvX25hbWVzJFYxLCBncmVwbCwgcGF0dGVybj0iXyIpXSkKCm1pdF9uYW1lcyA8LSByZWFkLnRhYmxlKCJkYXRhLWNldGFjZWFucy9NNDM3Nl9tdF9zaW1wbGlmaWVkX25ld05hbWVzX3JlbW92ZU91dGdyb3Vwcy5uZXgiLCBza2lwPTYsIGZpbGw9VCkKbWl0X25hbWVzIDwtIGRyb3BsZXZlbHMobWl0X25hbWVzJFYxW3NhcHBseShtaXRfbmFtZXMkVjEsIGdyZXBsLCBwYXR0ZXJuPSJfIildKQoKbnVjX25hbWVzIDwtIHJlYWQudGFibGUoImRhdGEtY2V0YWNlYW5zL000MzU4X251Y2xlYXJfc2ltcGxpZmllZF9uZXdOYW1lc19yZW1vdmVPdXRncm91cHMubmV4Iiwgc2tpcD02LCBmaWxsPVQpCm51Y19uYW1lcyA8LSBkcm9wbGV2ZWxzKG51Y19uYW1lcyRWMVtzYXBwbHkobnVjX25hbWVzJFYxLCBncmVwbCwgcGF0dGVybj0iXyIpXSkKCnNldGVxdWFsKHRheGEkdGF4b24sIHVuaW9uKHVuaW9uKG1vcnBob19uYW1lcywgbWl0X25hbWVzKSwgbnVjX25hbWVzKSkKYGBgCgpJZGVtIGF0IHRoZSBnZW5lcmljIGxldmVsIGZvciB0aGUgZ2VudXMgYW5hbHlzaXMuCgpgYGB7cn0Kb2NjdXJyZW5jZXNfd2l0aF9tb3JwaG9sb2d5X2dlbmVyYSA8LSBvY2N1cnJlbmNlc193aXRoX21vcnBob2xvZ3lbLXdoaWNoKG9jY3VycmVuY2VzX3dpdGhfbW9ycGhvbG9neSRUYXhvbiAlaW4lIGMoIkF0b2NldHVzX25hc2FsaXMiLCAiQnJhY2h5ZGVscGhpc19qYWh1YXllbnNpcyIsICJIYWJvcm9waG9jb2VuYV9taW51dHVzIiwgIkxvcGhvY2V0dXNfcmVwZW5uaW5naSIsICJPZG9iZW5vY2V0b3BzX3BlcnV2aWFudXMiLCAiT3Rla2Fpa2VhX2h1YXRhIiwgIlBhcmFwb250b3BvcmlhX3dpbHNvbmkiKSksXQpleHRhbnRfZ2VuZXJhIDwtIHJlYWQuY3N2MigiZGF0YS1jZXRhY2VhbnMvQ2V0YWNlYV9leHRhbnRfZ2VuZXJhLmNzdiIpCnN1bW1hcnkoZXh0YW50X2dlbmVyYSkKCmV4dGluY3RfZ2VuZXJhIDwtIGNldGFjZWFfcGJkYltjZXRhY2VhX3BiZGIkb2NjdXJyZW5jZV9ubyAlaW4lIG9jY3VycmVuY2VzX3dpdGhfbW9ycGhvbG9neV9nZW5lcmEkcGJkYl9vY2N1cmVuY2UubnVtYmVyLCBjKCJhY2NlcHRlZF9uYW1lIiwgIm1pbl9tYSIsICJtYXhfbWEiKV0KZXh0aW5jdF9nZW5lcmEkYWNjZXB0ZWRfbmFtZSA8LSBhcy5mYWN0b3IoZ3N1YigiICIsICJfIiwgZXh0aW5jdF9nZW5lcmEkYWNjZXB0ZWRfbmFtZSkpCm5hbWVzKGV4dGluY3RfZ2VuZXJhKSA8LSBuYW1lcyhleHRhbnRfZ2VuZXJhKQpzdW1tYXJ5KGV4dGluY3RfZ2VuZXJhKQoKZ2VuZXJhIDwtIHJiaW5kKGV4dGFudF9nZW5lcmEsIGV4dGluY3RfZ2VuZXJhKQpzdW1tYXJ5KGdlbmVyYSkKd3JpdGUudGFibGUoZ2VuZXJhLCBmaWxlID0gImRhdGEtY2V0YWNlYW5zL0NldGFjZWFfZ2VuZXJhLmNzdiIsIHF1b3RlID0gRiwgc2VwPSJcdCIsIHJvdy5uYW1lcyA9IEYpCmBgYAoKQ2hlY2sgdGhhdCB0aGUgbmFtZXMgaW4gdGhlIGRhdGFzZXRzIGFyZSBleGFjdGx5IHRoZSBzYW1lIGFzIGluIHRoZSBsaXN0IGFib3ZlLgoKYGBge3J9Cm1vcnBob19uYW1lc19nZW5lcmEgPC0gcmVhZC50YWJsZSgiZGF0YS1jZXRhY2VhbnMvbW9ycGhvX3NpbXBsaWZpZWRfbmV3TmFtZXNfZ2VuZXJhX3JlbW92ZU91dGdyb3Vwc1VuZGVzY3JpYmVkLm5leCIsIHNraXA9NiwgZmlsbD1UKQptb3JwaG9fbmFtZXNfZ2VuZXJhIDwtIGRyb3BsZXZlbHMobW9ycGhvX25hbWVzX2dlbmVyYSRWMVtzYXBwbHkobW9ycGhvX25hbWVzX2dlbmVyYSRWMSwgZ3JlcGwsIHBhdHRlcm49Il8iKV0pCgptaXRfbmFtZXNfZ2VuZXJhIDwtIHJlYWQudGFibGUoImRhdGEtY2V0YWNlYW5zL000Mzc2X210X3NpbXBsaWZpZWRfbmV3TmFtZXNfZ2VuZXJhX3JlbW92ZU91dGdyb3Vwcy5uZXgiLCBza2lwPTYsIGZpbGw9VCkKbWl0X25hbWVzX2dlbmVyYSA8LSBkcm9wbGV2ZWxzKG1pdF9uYW1lc19nZW5lcmEkVjFbc2FwcGx5KG1pdF9uYW1lc19nZW5lcmEkVjEsIGdyZXBsLCBwYXR0ZXJuPSJfIildKQoKbnVjX25hbWVzX2dlbmVyYSA8LSByZWFkLnRhYmxlKCJkYXRhLWNldGFjZWFucy9NNDM1OF9udWNsZWFyX3NpbXBsaWZpZWRfbmV3TmFtZXNfZ2VuZXJhX3JlbW92ZU91dGdyb3Vwcy5uZXgiLCBza2lwPTYsIGZpbGw9VCkKbnVjX25hbWVzX2dlbmVyYSA8LSBkcm9wbGV2ZWxzKG51Y19uYW1lc19nZW5lcmEkVjFbc2FwcGx5KG51Y19uYW1lc19nZW5lcmEkVjEsIGdyZXBsLCBwYXR0ZXJuPSJfIildKQoKc2V0ZXF1YWwoZ2VuZXJhJHRheG9uLCB1bmlvbih1bmlvbihtb3JwaG9fbmFtZXNfZ2VuZXJhLCBtaXRfbmFtZXNfZ2VuZXJhKSwgbnVjX25hbWVzX2dlbmVyYSkpCmBgYAoKUmVtb3ZlIHRob3NlIG9jY3VycmVuY2VzIGZyb20gb3VyIGluaXRpYWwgZGF0YXNldCB0byBhdm9pZCByZWR1bmRhbmN5LgoKYGBge3J9CmNldGFjZWFfcGJkYiA8LSBjZXRhY2VhX3BiZGJbIShjZXRhY2VhX3BiZGIkb2NjdXJyZW5jZV9ubyAlaW4lIG9jY3VycmVuY2VzX3dpdGhfbW9ycGhvbG9neSRwYmRiX29jY3VyZW5jZS5udW1iZXIpLF0KYGBgCgojIEV4cGxvcmUgdGhlIGRhdGFzZXQKIyMgUmVwYXJ0aXRpb24gdGhyb3VnaCB0aW1lCiMjIyBGdWxsIGZvc3NpbCByZWNvcmQKCmBgYHtyfQojIENvbXB1dGUgdGhlIG1lYW4gYWdlIGluIHRoZSB0aW1lIGludGVydmFsCmNldGFjZWFfcGJkYiRhZ2VfbWVhbiA8LSAoY2V0YWNlYV9wYmRiJG1pbl9tYStjZXRhY2VhX3BiZGIkbWF4X21hKS8yCgpnZ3Bsb3QoY2V0YWNlYV9wYmRiLCBhZXMoeD0tYWdlX21lYW4sIHk9cm5vcm0obGVuZ3RoKGFnZV9tZWFuKSwgMSwgMC4wNSkpKSArCiAgZ2VvbV9wb2ludChjZXg9MC4xLCBhbHBoYT0wLjUpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJUaW1lIChNeSkiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKG5hbWUgPSAiT2NjdXJyZW5jZXMiLCBsaW1pdHMgPSBjKDAuNSwgMS41KSkgKwogIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZT0iQWNjZXB0ZWQgcmFuayIpICsKICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMubGluZS54ID0gZWxlbWVudF9saW5lKHNpemUgPSAwLjUsIGxpbmV0eXBlID0gInNvbGlkIiwgY29sb3VyID0gImJsYWNrIiksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpKSArCiAgZ2d0aXRsZShwYXN0ZSgiUmVwYXJ0aXRpb24gb2YiLCBkaW0oY2V0YWNlYV9wYmRiKVsxXSwgInJlY29yZGVkIG9jY3VycmVuY2VzIHRocm91Z2ggdGltZSIpKQoKZ2dwbG90KGNldGFjZWFfcGJkYiwgYWVzKHg9LWFnZV9tZWFuKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKwogIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIlRpbWUgKE15KSIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobmFtZSA9ICJOdW1iZXIgb2Ygb2NjdXJyZW5jZXMiKSArCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lPSJBY2NlcHRlZCByYW5rIikgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBsZWdlbmQucG9zaXRpb249ImJvdHRvbSIpICsKICBnZ3RpdGxlKHBhc3RlKCJFdm9sdXRpb24gb2YgdGhlIG51bWJlciBvY2N1cnJlbmNlcyB0aHJvdWdoIHRpbWUgKCB0b3RhbCBvZiIsIGRpbShjZXRhY2VhX3BiZGIpWzFdLCAiKSAtIE1pZHBvaW50IikpCmBgYAoKJFx0byQgTnVtZXJvdXMgb2NjdXJyZW5jZXMgc2VlbSB0byBoYXZlIHRoZSBzYW1lIGFnZSBpbnRlcnZhbCBzbyBpbiBvcmRlciB0byBhdm9pZCBjbHVzdGVycyBsZXQncyBkcmF3IHRoZW0gdW5pZm9ybWx5IGluIHRoZWlyIHN0cmF0aWdyYXBoaWMgcmFuZ2UgcmF0aGVyIHRoYW4gdGFraW5nIHRoZSBtZWFuLgoKYGBge3J9CiMgRHJhdyBvY2N1cnJlbmNlIGFnZSB1bmlmb3JtYWxseSBpbiB0aGUgdGltZSBpbnRlcnZhbApjZXRhY2VhX3BiZGIkYWdlX3J1bmlmIDwtIG1hcHBseShmdW5jdGlvbihtLCBNKXtydW5pZihuPTEsIG1pbj1tLCBtYXg9TSl9LCBjZXRhY2VhX3BiZGIkbWluX21hLCBjZXRhY2VhX3BiZGIkbWF4X21hKQoKZ2dwbG90KGNldGFjZWFfcGJkYiwgYWVzKHg9LWFnZV9ydW5pZiwgeT1ybm9ybShsZW5ndGgoYWdlX3J1bmlmKSwgMSwgMC4wNSkpKSArCiAgZ2VvbV9wb2ludChjZXg9MC4xLCBhbHBoYT0wLjUpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJUaW1lIChNeSkiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKG5hbWUgPSAiT2NjdXJyZW5jZXMiLCBsaW1pdHMgPSBjKDAuNSwgMS41KSkgKwogIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZT0iQWNjZXB0ZWQgcmFuayIpICsKICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMubGluZS54ID0gZWxlbWVudF9saW5lKHNpemUgPSAwLjUsIGxpbmV0eXBlID0gInNvbGlkIiwgY29sb3VyID0gImJsYWNrIiksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpKSArCiAgZ2d0aXRsZShwYXN0ZSgiUmVwYXJ0aXRpb24gb2YiLCBkaW0oY2V0YWNlYV9wYmRiKVsxXSwgInJlY29yZGVkIG9jY3VycmVuY2VzIHRocm91Z2ggdGltZSIpKQoKZ2dwbG90KGNldGFjZWFfcGJkYiwgYWVzKHg9LWFnZV9ydW5pZikpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJUaW1lIChNeSkiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKG5hbWUgPSAiTnVtYmVyIG9mIG9jY3VycmVuY2VzIikgKwogIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZT0iQWNjZXB0ZWQgcmFuayIpICsKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uPSJib3R0b20iKSArCiAgZ2d0aXRsZShwYXN0ZSgiRXZvbHV0aW9uIG9mIHRoZSBudW1iZXIgb2NjdXJyZW5jZXMgdGhyb3VnaCB0aW1lICggdG90YWwgb2YiLCBkaW0oY2V0YWNlYV9wYmRiKVsxXSwgIikgLSBVbmlmb3JtIGRyYXciKSkKYGBgCgokXHRvJCBUaGUgcmVwYXJ0aXRpb24gc2VlbXMgbXVjaCBzbW9vdGhlciBub3cuCgojIyMgU3Vic2FtcGxpbmcKClRoZXNlIG9jY3VycmVuY2VzIGFyZSB0b28gbnVtZXJvdXMgZm9yIG91ciBjdXJyZW50IGltcGxlbWVudGF0aW9uLCBsZXQncyBzdWJzYW1wbGUgYSBmcmFjdGlvbiBvZiB0aGVtIGZvciBub3cuCgpgYGB7cn0KY2V0YWNlYV9wYmRiX3N1YnNhbXBsZWQgPC0gc2FtcGxlX24oY2V0YWNlYV9wYmRiLCBzaXplPXJvdW5kKGxlbmd0aChhZ2VfcnVuaWYpKjAuMTApKQoKZ2dwbG90KGNldGFjZWFfcGJkYl9zdWJzYW1wbGVkLCBhZXMoeD0tYWdlX3J1bmlmLCB5PXJub3JtKGxlbmd0aChhZ2VfcnVuaWYpLCAxLCAwLjA1KSkpICsKICBnZW9tX3BvaW50KGNleD0wLjUsIGFscGhhPTAuNSkgKwogIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIlRpbWUgKE15KSIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobmFtZSA9ICJPY2N1cnJlbmNlcyIsIGxpbWl0cyA9IGMoMC41LCAxLjUpKSArCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lPSJBY2NlcHRlZCByYW5rIikgKwogIHRoZW1lKHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy5saW5lLnggPSBlbGVtZW50X2xpbmUoc2l6ZSA9IDAuNSwgbGluZXR5cGUgPSAic29saWQiLCBjb2xvdXIgPSAiYmxhY2siKSwKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCkpICsKICBnZ3RpdGxlKHBhc3RlKCJSZXBhcnRpdGlvbiBvZiIsIGRpbShjZXRhY2VhX3BiZGJfc3Vic2FtcGxlZClbMV0sICJyZWNvcmRlZCBvY2N1cnJlbmNlcyB0aHJvdWdoIHRpbWUiKSkKCmdncGxvdChjZXRhY2VhX3BiZGJfc3Vic2FtcGxlZCwgYWVzKHg9LWFnZV9ydW5pZikpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJUaW1lIChNeSkiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKG5hbWUgPSAiTnVtYmVyIG9mIG9jY3VycmVuY2VzIikgKwogIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZT0iQWNjZXB0ZWQgcmFuayIpICsKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uPSJib3R0b20iKSArCiAgZ2d0aXRsZShwYXN0ZSgiRXZvbHV0aW9uIG9mIHRoZSBudW1iZXIgb2NjdXJyZW5jZXMgdGhyb3VnaCB0aW1lICggdG90YWwgb2YiLCBkaW0oY2V0YWNlYV9wYmRiX3N1YnNhbXBsZWQpWzFdLCAiKSAtIFVuaWZvcm0gZHJhdyIpKQpgYGAKCiRcdG8kIFRoZSBkaXN0cmlidXRpb24gbG9va3Mgc2ltaWxhciwgd2l0aCBzb21lIG5vaXNlIGR1ZSB0byBoaWdoZXIgdmFyaWFuY2Ugd2l0aCBzbWFsbGVyIHNhbXBsZS4KCmBgYHtyfQp3cml0ZShjZXRhY2VhX3BiZGIkYWdlX21lYW4sIGZpbGUgPSAiZGF0YS1jZXRhY2VhbnMvQ2V0YWNlYV9vY2N1cnJlbmNlc19tZWFuX2FnZS5jc3YiLCBzZXA9IjsgIiwgbmNvbHVtbnMgPSBkaW0oY2V0YWNlYV9wYmRiKVsxXSkKd3JpdGUoY2V0YWNlYV9wYmRiJGFnZV9ydW5pZiwgZmlsZSA9ICJkYXRhLWNldGFjZWFucy9DZXRhY2VhX2FnZV9ydW5pZl9hZ2UuY3N2Iiwgc2VwPSI7ICIsIG5jb2x1bW5zID0gZGltKGNldGFjZWFfcGJkYilbMV0pCndyaXRlKGNldGFjZWFfcGJkYl9zdWJzYW1wbGVkJGFnZV9ydW5pZiwgZmlsZSA9ICJkYXRhLWNldGFjZWFucy9DZXRhY2VhX2FnZV9ydW5pZl9hZ2Vfc3Vic2FtcGxlZC5jc3YiLCBzZXA9IjsgIiwgbmNvbHVtbnMgPSBkaW0oY2V0YWNlYV9wYmRiX3N1YnNhbXBsZWQpWzFdKQpgYGAKCiMjIFJlcGFydGl0aW9uIGFtb25nIGFjY2VwdGVkIHJhbmtzCiMjIyBQaWUgY2hhcnQKCmBgYHtyfQpnZ3Bsb3QoY2V0YWNlYV9wYmRiLCBhZXMoeD1mYWN0b3IocmVjb3JkX3R5cGUpLCBmaWxsPWFjY2VwdGVkX3JhbmspKSArCiAgZ2VvbV9iYXIod2lkdGggPSAxLCBzdGF0ID0gImNvdW50IikgKwogIGNvb3JkX3BvbGFyKCJ5IikgKyAKICBzY2FsZV9maWxsX2Rpc2NyZXRlKG5hbWU9IkFjY2VwdGVkIHJhbmsiKSArCiAgbGFicyh4ID0gTlVMTCwgeSA9IE5VTEwsIGZpbGwgPSBOVUxMLCB0aXRsZSA9ICJSZXBhcnRpdGlvbiBvZiBvY2N1cnJlbmNlcyBhbW9uZyBhY2NlcHRlZCByYW5rcyIpCmBgYAoKJFx0byQgSGFsZiBvZiB0aGUgb2NjdXJyZW5jZXMgYXJlIGlkZW50aWZpZWQgYXQgdGhlIGxldmVsIG9mIHRoZSBzZWNpZXMgYW5kIDEvMyBhdCB0aGUgZ2VudXMgb3IgZmFtaWx5LgoKU29tZSBjbGFkZXMgYXJlIHVucmFua2VkIDoKCmBgYHtyfQp0YWJsZShhcy5jaGFyYWN0ZXIoY2V0YWNlYV9wYmRiW2NldGFjZWFfcGJkYiRhY2NlcHRlZF9yYW5rPT0idW5yYW5rZWQgY2xhZGUiLF0kYWNjZXB0ZWRfbmFtZSkpCmBgYAoKIyMjIFRpbWUgcmVwYXJ0aXRpb24gYnkgcmFuawoKYGBge3IgZmlnLmhlaWdodD02fQpnZ3Bsb3QoY2V0YWNlYV9wYmRiW2NldGFjZWFfcGJkYiRhY2NlcHRlZF9yYW5rICVpbiUgYygic3BlY2llcyIsICJnZW51cyIpLF0sIGFlcyh4PS1hZ2VfcnVuaWYsIGZpbGw9YWNjZXB0ZWRfcmFuaykpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuMSkgKwogIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIlRpbWUgKE15KSIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobmFtZSA9ICJOdW1iZXIgb2Ygb2NjdXJyZW5jZXMiKSArCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lPSJBY2NlcHRlZCByYW5rIikgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIGdndGl0bGUoIkV2b2x1dGlvbiBvZiB0aGUgbnVtYmVyIG9jY3VycmVuY2VzIHRocm91Z2ggdGltZSAoMC4xIE15IHRpbWUgYmlucyksIGJ5IGFjY2VwdGVkIHJhbmsiKSArCiAgZmFjZXRfZ3JpZChhY2NlcHRlZF9yYW5rIH4gLiwgc2NhbGVzPSJmcmVlIikKCiMgQ291bnQgdGhlIG51bWJlciBvZiBvY2N1cnJlbmNlcyB3aXRoIHRoZSBzYW1lIGFjY2VwdGVkIG5hbWUKY2V0YWNlYV9wYmRiJGFjY2VwdGVkX25hbWVfY291bnQgPC0gc2FwcGx5KGNldGFjZWFfcGJkYiRhY2NlcHRlZF9uYW1lLCBmdW5jdGlvbih4KXt0YWJsZShjZXRhY2VhX3BiZGIkYWNjZXB0ZWRfbmFtZSlbeF19KQojIEdldCB0aGUgZHVyYXRpb24gb2YgdGhlIHRpbWUgaW50ZXJ2YWxzCmNldGFjZWFfcGJkYiRhZ2VfcmFuZ2UgPC0gY2V0YWNlYV9wYmRiJG1heF9tYS1jZXRhY2VhX3BiZGIkbWluX21hCgpnZ3Bsb3QoY2V0YWNlYV9wYmRiLCBhZXMoeD1hY2NlcHRlZF9uYW1lX2NvdW50L2FnZV9yYW5nZSwgZmlsbD1mYWN0b3IobWF4X21hKSkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aD0wLjEpICsKICBzY2FsZV94X2NvbnRpbnVvdXModHJhbnM9ImxvZzEwIiwgbmFtZT0iRGVuc2l0eSBvZiBvY2N1cnJlbmNlcyAobnVtYmVyL015KSIpICsKICBzY2FsZV9maWxsX2Rpc2NyZXRlKG5hbWU9Ik1heGltdW0gYWdlIChNeSkiKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpKSArCiAgZ2d0aXRsZSgiRGlzdHJpYnV0aW9ucyBvY2N1cnJlbmNlIGRlbnNpdHksIGJ5IGFjY2VwdGVkIHJhbmsiKSArCiAgZmFjZXRfZ3JpZChhY2NlcHRlZF9yYW5rIH4gLikKCmdncGxvdChjZXRhY2VhX3BiZGIsIGFlcyh4PWFjY2VwdGVkX25hbWVfY291bnQvYWdlX3JhbmdlLCBmaWxsPWZhY3Rvcihyb3VuZChhZ2VfcmFuZ2UsIDIpKSkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aD0wLjEpICsKICBzY2FsZV94X2NvbnRpbnVvdXModHJhbnM9ImxvZzEwIiwgbmFtZT0iRGVuc2l0eSBvZiBvY2N1cnJlbmNlcyAobnVtYmVyL015KSIpICsKICBzY2FsZV9maWxsX2Rpc2NyZXRlKG5hbWU9IkFnZSByYW5nZSAoTXkpIikgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIGdndGl0bGUoIkRpc3RyaWJ1dGlvbnMgb2NjdXJyZW5jZSBkZW5zaXR5LCBieSBhY2NlcHRlZCByYW5rIikgKwogIGZhY2V0X2dyaWQoYWNjZXB0ZWRfcmFuayB+IC4pCmBgYAoKJFx0byQgQXBwYXJlbnQgaHVnZSBjbHVzdGVyIG9mIG9jY3VycmVuY2VzIGluIHJlY2VudCB0aW1lcywgd2l0aCB2ZXJ5IHByZWNpc2UgZGF0aW5nID0gQXJ0ZWZhY3QgZHVlIHRvIHRoZSAiUHVsbCBvZiB0aGUgUmVjZW50IiBlZmZlY3QgPyAkXHRvJCBXZSBkZWNpZGVkIHRvICoqcmVtb3ZlIGFsbCBMYXRlIFBsZWlzdG9jZW5lIGFuZCBIb2xvY2VuZSBvY2N1cnJlbmNlcyoqICh0aHVzIHNldHRpbmcgdGhlICRcb21lZ2EkLXNhbXBsaW5nIHRvIDApIGluIG9yZGVyIHRvIGF2b2lkIHRoaXMgYmlhcy4KCmBgYHtyfQpDZXRhY2VhX29jYyA8LSBjZXRhY2VhX3BiZGJbY2V0YWNlYV9wYmRiJGFnZV9ydW5pZiA+IDAuMTI2LF0KCmRhdGEuZnJhbWUoY2V0YWNlYV9wYmRiID0gZGltKGNldGFjZWFfcGJkYilbMV0sCiAgICAgICAgICAgQ2V0YWNlYV9vY2MgPSBkaW0oQ2V0YWNlYV9vY2MpWzFdLAogICAgICAgICAgIHJlbW92ZWQgPSBkaW0oY2V0YWNlYV9wYmRiKVsxXS1kaW0oQ2V0YWNlYV9vY2MpWzFdLAogICAgICAgICAgIHJvdy5uYW1lcyA9ICJOdW1iZXIgb2Ygb2NjdXJyZW5jZXMiKQpgYGAKCmBgYHtyIGZpZy5oZWlnaHQ9Nn0KZ2dwbG90KENldGFjZWFfb2NjWyFDZXRhY2VhX29jYyRhY2NlcHRlZF9yYW5rICVpbiUgYygic3Vic3BlY2llcyIsICJpbmZyYW9yZGVyIiksXSwgYWVzKHg9LWFnZV9ydW5pZiwgZmlsbD1hY2NlcHRlZF9yYW5rKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC41KSArCiAgc2NhbGVfeF9jb250aW51b3VzKG5hbWUgPSAiVGltZSAoTXkpIikgKwogIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gIk51bWJlciBvZiBvY2N1cnJlbmNlcyIpICsKICBzY2FsZV9maWxsX2Rpc2NyZXRlKG5hbWU9IkFjY2VwdGVkIHJhbmsiKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpKSArCiAgZ2d0aXRsZSgiRXZvbHV0aW9uIG9mIHRoZSBudW1iZXIgb2NjdXJyZW5jZXMgdGhyb3VnaCB0aW1lICgwLjUgTXkgdGltZSBiaW5zKSwgYnkgYWNjZXB0ZWQgcmFuayIpICsKICBmYWNldF9ncmlkKGFjY2VwdGVkX3JhbmsgfiAuLCBzY2FsZXM9ImZyZWUiKQpgYGAKCiRcdG8kIFdlIG9ic2VydmUgc2ltaWxhciB0cmVuZHMgYXQgZWFjaCByYW5rLCB3aXRoIHBlYWtzIGF0IH4xNU15IGFuZCB+NU15LgoKIyMjIFJlZHVuZGFuY3kgb2Ygb2NjdXJyZW5jZXMgd2l0aCB0aGUgc2FtZSBhY2NlcHRlZCBuYW1lCgpgYGB7ciBmaWcuaGVpZ2h0PTZ9CmdncGxvdChjZXRhY2VhX3BiZGIsIGFlcyh4PXJlb3JkZXIoYWNjZXB0ZWRfbmFtZSwgdGFibGUoYWNjZXB0ZWRfbmFtZSlbYWNjZXB0ZWRfbmFtZV0pLCBmaWxsPWFjY2VwdGVkX3JhbmspKSArCiAgZ2VvbV9iYXIoc3RhdD0iY291bnQiKSArIAogIHNjYWxlX3hfZGlzY3JldGUobmFtZSA9ICJBY2NlcHRlZCBuYW1lcyIpICsKICBzY2FsZV95X2NvbnRpbnVvdXModHJhbnMgPSAibG9nMTAiLCBuYW1lID0gIk51bWJlciBvZiBjb3JyZXNwb25kaW5nIG9jY3VycmVuY2VzIChsb2ctc2NhbGUpIikgKwogIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZT0iQWNjZXB0ZWQgcmFuayIpICsKICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy54PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uPSJib3R0b20iKSArCiAgZ2d0aXRsZSgiRGlzdHJpYnV0aW9ucyBvZiB0aGUgbnVtYmVyIG9mIG9jY3VycmVuY2VzIHdpdGggdGhlIHNhbWUgYWNjZXB0ZWQgbmFtZSwgYnkgYWNjZXB0ZWQgcmFuayIpICsKICBmYWNldF9ncmlkKC4gfiBhY2NlcHRlZF9yYW5rLCBzY2FsZXM9ImZyZWVfeCIpCmBgYAoKJFx0byQgfkhhbGYgb2Ygc3BlY2llcy9nZW5lcmEvc3ViZmFtaWxpZXMgaGF2ZSBvbmx5IG9uZSBzcGVjaW1lbiBieSBhY2NlcHRlZCBuYW1lLCBidXQgaXQgY291bGQgZ28gdXAgdG8gfjUwIHdpdGhpbiB0aGUgc2FtZSBzcGVjaWVzIGFuZCB+MjAwIG9jY3VycmVuY2VzIHdpdGhpbiB0aGUgc2FtZSBzdWJvcmRlci4gKipUaG9zZSBkaWZmZXJlbmNlcyB3aWxsIGhhdmUgdG8gYmUgY29ycmVjdGVkIGJlY2F1c2UgaW4gb3VyIG1vZGVsIGFsbCBzcGVjaWVzIGFyZSB1cHBvc2VkIHRvIGhhdmUgdGhlIHNhbWUgYWJ1bmRhbmNlIChpZGVudGljYWwgc2FtcGxpbmcgcmF0ZXMgYW1vbmcgYnJhbmNoZXMpLioqCgokXGltcGxpZXMkIE91ciBnb2FsIG5vdyB3aWxsIGJlIHRvIGNvcnJlY3QgdGhpcyBhYnVuZGFuY2UgYmlhcy4KCiMjIFRpbWUgaW50ZXJ2YWxzID0gc3RyYXRpZ3JhcGhpYyBhZ2UgdW5jZXJ0YWludHkKIyMjIE1pbmltdW0gYW5kIG1heGltdW0gc3RyYXRpZ3JhcGhpYyBsaW1pdHMKCmBgYHtyIGZpZy5oZWlnaHQ9NH0KZ2dwbG90KGNldGFjZWFfcGJkYiwgYWVzKHg9cmVvcmRlcihsYXRlX2ludGVydmFsLCAtbWF4X21hLCBtZWRpYW4pLCBncm91cCA9IC1tYXhfbWEsIGZpbGw9LW1heF9tYSkpICsKICBnZW9tX2JhcihzdGF0PSJjb3VudCIpICsgCiAgc2NhbGVfeF9kaXNjcmV0ZShuYW1lID0gIkxhdGUgU3RyYXRpZ3JhcGhpYyBMaW1pdCIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobmFtZSA9ICJOdW1iZXIgb2YgY29ycmVzcG9uZGluZyBvY2N1cnJlbmNlcyIpICsKICBzY2FsZV9maWxsX2NvbnRpbnVvdXMobmFtZSA9ICJNYXhpbXVtIEFnZSAoTXkpIikgKwogIGdndGl0bGUoIkRpc3RyaWJ1dGlvbiBvZiBtYXhpbXVtIHN0cmF0aWdyYXBoaWMgYWdlcyIpICsKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uPSJib3R0b20iLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0ID0gMSkpCgpnZ3Bsb3QoY2V0YWNlYV9wYmRiLCBhZXMoeD1yZW9yZGVyKGVhcmx5X2ludGVydmFsLCAtbWluX21hLCBtZWRpYW4pLCBncm91cCA9IC1taW5fbWEsIGZpbGw9LW1pbl9tYSkpICsKICBnZW9tX2JhcihzdGF0PSJjb3VudCIpICsgCiAgc2NhbGVfeF9kaXNjcmV0ZShuYW1lID0gIkVhcmx5IFN0cmF0aWdyYXBoaWMgTGltaXQiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKG5hbWUgPSAiTnVtYmVyIG9mIGNvcnJlc3BvbmRpbmcgb2NjdXJyZW5jZXMiKSArCiAgc2NhbGVfZmlsbF9jb250aW51b3VzKG5hbWUgPSAiTWluaW11bSBBZ2UgKE15KSIpICsKICBnZ3RpdGxlKCJEaXN0cmlidXRpb24gb2YgbWluaW11bSBzdHJhdGlncmFwaGljIGFnZXMiKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIiwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdCA9IDEpKQpgYGAKCiRcdG8kIE1vc3Qgc3BlY2llcyBoYXZlIGEgZWFybHkgYnV0IG5vdCBhIGxhdGUgc3RyYXRpZ3JhcGhpYyBsaW1pdC4KCiMjIyBNaW5pbXVtIGFuZCBtYXhpbXVtIGFnZXMKCmBgYHtyIH0KIyBHZXQgdGhlIHN0cmF0aWdyYXBoaWMgaW50ZXJ2YWwgb2YgdGltZSB1bmNlcnRhaW50eQpDZXRhY2VhX29jYyRhZ2VfaW50ZXJ2YWwgPC0gbWFwcGx5KGZ1bmN0aW9uKG1pbl9hZ2UsIG1heF9hZ2Upe3Bhc3RlKCJbIiwtbWF4X2FnZSwiLCAiLC1taW5fYWdlLCJdIiwgc2VwID0gIiIpfSwgQ2V0YWNlYV9vY2MkbWluX21hLCBDZXRhY2VhX29jYyRtYXhfbWEpCgpnZ3Bsb3QoQ2V0YWNlYV9vY2MsIGFlcyh4PS1tYXhfbWEsIHk9YWdlX2ludGVydmFsKSkgKwogIGdlb21fc2VnbWVudChhZXMoeCA9IC1tYXhfbWEsIHkgPSByZW9yZGVyKGFnZV9pbnRlcnZhbCwgLWFnZV9tZWFuKSwgeGVuZCA9IC1taW5fbWEsIHllbmQ9cmVvcmRlcihhZ2VfaW50ZXJ2YWwsIC1hZ2VfbWVhbiksIGNvbG9yPS1hZ2VfbWVhbikpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJUaW1lIChNeSkiKSArCiAgc2NhbGVfeV9kaXNjcmV0ZShuYW1lID0gIkFnZSBpbnRlcnZhbHMiKSArCiAgbGFicyhjb2xvdXI9Ik1lYW4gYWdlIikgKwogIGdndGl0bGUoIkRpc3RyaWJ1dGlvbiBvZiBhZ2UgaW50ZXJ2YWxzIikgKwogIHRoZW1lKGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnk9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSkKYGBgCgojIyBUaW1lIHJhbmdlcyA9IGR1cmF0aW9uIG9mIHRoZSB0aW1lIGludGVydmFscwojIyMgQ291bnQgb2NjdXJyZW5jZXMgYnkgYWNjZXB0ZWQgbmFtZQoKYGBge3IgZmlnLmhlaWdodD04fQojIENvdW50IHRoZSBudW1iZXIgb2Ygb2NjdXJyZW5jZXMgd2l0aCB0aGUgc2FtZSBhY2NlcHRlZCBuYW1lCkNldGFjZWFfb2NjJGFjY2VwdGVkX25hbWVfY291bnQgPC0gc2FwcGx5KENldGFjZWFfb2NjJGFjY2VwdGVkX25hbWUsIGZ1bmN0aW9uKHgpe3RhYmxlKENldGFjZWFfb2NjJGFjY2VwdGVkX25hbWUpW3hdfSkKCm15X2JyZWFrcyA8LSBjKDEsMywxMCwzNSwxMDAsbWF4KENldGFjZWFfb2NjJGFjY2VwdGVkX25hbWVfY291bnQpKQoKZ2dwbG90KENldGFjZWFfb2NjWyEoQ2V0YWNlYV9vY2MkYWNjZXB0ZWRfcmFuayAlaW4lIGMoInNwZWNpZXMiLCAiZ2VudXMiLCAiZmFtaWx5IikpLF0sIGFlcyh4PS1tYXhfbWEsIHk9YWNjZXB0ZWRfbmFtZSkpICsKICBnZW9tX3NlZ21lbnQoYWVzKHggPSAtbWF4X21hLCB5ID0gcmVvcmRlcihhY2NlcHRlZF9uYW1lLCAtYWdlX21lYW4pLCB4ZW5kID0gLW1pbl9tYSwgeWVuZD1yZW9yZGVyKGFjY2VwdGVkX25hbWUsIC1hZ2VfbWVhbiksIGNvbG9yPWFjY2VwdGVkX25hbWVfY291bnQpLCBhcnJvdz1hcnJvdyhlbmRzID0gImJvdGgiLCBhbmdsZT05MCwgbGVuZ3RoID0gdW5pdCgxLCAibW0iKSksIGFscGhhPTAuNSkgKwogIGdlb21fcG9pbnQoYWVzKHg9LWFnZV9ydW5pZiksIGNvbD0icmVkIiwgY2V4PTEsIGFscGhhPTAuMykgKwogIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIlRpbWUgKE15KSIpICsKICBzY2FsZV95X2Rpc2NyZXRlKG5hbWUgPSAiQWNjZXB0ZWQgcmFua3MiKSArCiAgbGFicyhjb2xvdXI9IkFjY2VwdGVkIG5hbWVzIGNvdW50IikgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50bihjb2xvdXJzID0gYygiZGFya2JsdWUiLCAiZm9yZXN0Z3JlZW4iLCAiYmxhY2siKSwgdHJhbnM9ImxvZyIsIGJyZWFrcz1teV9icmVha3MsIGxhYmVscz1teV9icmVha3MpICsgCiAgZ2d0aXRsZSgiRGlzdHJpYnV0aW9ucyBvZiBmb3NzaWwgYWdlIHJhbmdlcywgYnkgYWNjZXB0ZWQgcmFuayIpICsKICBmYWNldF9ncmlkKGFjY2VwdGVkX3JhbmsgfiAuLCBzY2FsZXMgPSAiZnJlZSIpCgpnZ3Bsb3QoQ2V0YWNlYV9vY2NbQ2V0YWNlYV9vY2MkYWNjZXB0ZWRfcmFuayA9PSJzcGVjaWVzIixdLCBhZXMoeD0tbWF4X21hLCB5PWFjY2VwdGVkX25hbWUpKSArCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gLW1heF9tYSwgeSA9IHJlb3JkZXIoYWNjZXB0ZWRfbmFtZSwgLWFnZV9tZWFuKSwgeGVuZCA9IC1taW5fbWEsIHllbmQ9cmVvcmRlcihhY2NlcHRlZF9uYW1lLCAtYWdlX21lYW4pLCBjb2xvcj1hY2NlcHRlZF9uYW1lX2NvdW50KSwgYXJyb3c9YXJyb3coZW5kcyA9ICJib3RoIiwgYW5nbGU9OTAsIGxlbmd0aCA9IHVuaXQoMSwgIm1tIikpLCBhbHBoYT0wLjUpICsKICBnZW9tX3BvaW50KGFlcyh4PS1hZ2VfcnVuaWYpLCBjb2w9InJlZCIsIGNleD0xLCBhbHBoYT0wLjMpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJUaW1lIChNeSkiKSArCiAgc2NhbGVfeV9kaXNjcmV0ZShuYW1lID0gIkFnZSByYW5nZXMiKSArCiAgbGFicyhjb2xvdXI9IkFjY2VwdGVkIG5hbWVzIGNvdW50IikgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X3RleHQoc2l6ZT0yKSkgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50bihjb2xvdXJzID0gYygiZGFya2JsdWUiLCAiZm9yZXN0Z3JlZW4iLCAiYmxhY2siKSwgdHJhbnM9ImxvZyIsIGJyZWFrcz1teV9icmVha3MsIGxhYmVscz1teV9icmVha3MpICsgCiAgZ2d0aXRsZSgiRGlzdHJpYnV0aW9ucyBvZiBmb3NzaWwgYWdlIHJhbmdlcyAoc3BlY2llcykiKSArCiAgZmFjZXRfZ3JpZChhY2NlcHRlZF9yYW5rIH4gLiwgc2NhbGVzID0gImZyZWUiKQoKZ2dwbG90KENldGFjZWFfb2NjW0NldGFjZWFfb2NjJGFjY2VwdGVkX3JhbmsgPT0iZ2VudXMiLF0sIGFlcyh4PS1tYXhfbWEsIHk9YWNjZXB0ZWRfbmFtZSkpICsKICBnZW9tX3NlZ21lbnQoYWVzKHggPSAtbWF4X21hLCB5ID0gcmVvcmRlcihhY2NlcHRlZF9uYW1lLCAtYWdlX21lYW4pLCB4ZW5kID0gLW1pbl9tYSwgeWVuZD1yZW9yZGVyKGFjY2VwdGVkX25hbWUsIC1hZ2VfbWVhbiksIGNvbG9yPWFjY2VwdGVkX25hbWVfY291bnQpLCBhcnJvdz1hcnJvdyhlbmRzID0gImJvdGgiLCBhbmdsZT05MCwgbGVuZ3RoID0gdW5pdCgxLCAibW0iKSksIGFscGhhPTAuNSkgKwogIGdlb21fcG9pbnQoYWVzKHg9LWFnZV9ydW5pZiksIGNvbD0icmVkIiwgY2V4PTEsIGFscGhhPTAuMykgKwogIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIlRpbWUgKE15KSIpICsKICBzY2FsZV95X2Rpc2NyZXRlKG5hbWUgPSAiR2VudXMiKSArCiAgbGFicyhjb2xvdXI9IkFjY2VwdGVkIG5hbWVzIGNvdW50IikgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X3RleHQoc2l6ZT02KSkgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50bihjb2xvdXJzID0gYygiZGFya2JsdWUiLCAiZm9yZXN0Z3JlZW4iLCAiYmxhY2siKSwgdHJhbnM9ImxvZyIsIGJyZWFrcz1teV9icmVha3MsIGxhYmVscz1teV9icmVha3MpICsgCiAgZ2d0aXRsZSgiRGlzdHJpYnV0aW9ucyBvZiBmb3NzaWwgYWdlIHJhbmdlcyAoZ2VuZXJhKSIpICsKICBmYWNldF9ncmlkKGFjY2VwdGVkX3JhbmsgfiAuLCBzY2FsZXMgPSAiZnJlZSIpCgpnZ3Bsb3QoQ2V0YWNlYV9vY2NbQ2V0YWNlYV9vY2MkYWNjZXB0ZWRfcmFuayA9PSJmYW1pbHkiLF0sIGFlcyh4PS1tYXhfbWEsIHk9YWNjZXB0ZWRfbmFtZSkpICsKICBnZW9tX3NlZ21lbnQoYWVzKHggPSAtbWF4X21hLCB5ID0gcmVvcmRlcihhY2NlcHRlZF9uYW1lLCAtYWdlX21lYW4pLCB4ZW5kID0gLW1pbl9tYSwgeWVuZD1yZW9yZGVyKGFjY2VwdGVkX25hbWUsIC1hZ2VfbWVhbiksIGNvbG9yPWFjY2VwdGVkX25hbWVfY291bnQpLCBhcnJvdz1hcnJvdyhlbmRzID0gImJvdGgiLCBhbmdsZT05MCwgbGVuZ3RoID0gdW5pdCgxLCAibW0iKSksIGFscGhhPTAuNSkgKwogIGdlb21fcG9pbnQoYWVzKHg9LWFnZV9ydW5pZiksIGNvbD0icmVkIiwgY2V4PTEsIGFscGhhPTAuMykgKwogIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIlRpbWUgKE15KSIpICsKICBzY2FsZV95X2Rpc2NyZXRlKG5hbWUgPSAiR2VudXMiKSArCiAgbGFicyhjb2xvdXI9IkFjY2VwdGVkIG5hbWVzIGNvdW50IikgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50bihjb2xvdXJzID0gYygiZGFya2JsdWUiLCAiZm9yZXN0Z3JlZW4iLCAiYmxhY2siKSwgdHJhbnM9ImxvZyIsIGJyZWFrcz1teV9icmVha3MsIGxhYmVscz1teV9icmVha3MpICsgCiAgZ2d0aXRsZSgiRGlzdHJpYnV0aW9ucyBvZiBmb3NzaWwgYWdlIHJhbmdlcyAoZmFtaWxpZXMpIikgKwogIGZhY2V0X2dyaWQoYWNjZXB0ZWRfcmFuayB+IC4sIHNjYWxlcyA9ICJmcmVlIikKYGBgCgokXHRvJCBTb21lIG9jY3VycmVuY2VzIGhhdmUgdG9vIG11Y2ggYWdlIHVuY2VydGFpbnR5LCB0aGV5IHJpc2sgdG8gYXJ0aWZpY2lhbGx5IGluY3JlYXNlIHNwZWNpZXMgZHVyYXRpb25zLgoKIyMjIFJlbW92ZSBvY2N1cnJlbmNlcyB3aXRoIGhpZ2hseSB1bmNlcnRhaW4gZGF0aW5nIChyYW5nZSA+IDEwTXkpCgpgYGB7cn0KIyBHZXQgdGhlIGR1cmF0aW9uIG9mIHRoZSB0aW1lIGludGVydmFscwpDZXRhY2VhX29jYyRhZ2VfcmFuZ2UgPC0gQ2V0YWNlYV9vY2MkbWF4X21hLUNldGFjZWFfb2NjJG1pbl9tYQojIE9jY3VycmVuY2VzIHdob3NlIHRpbWUgcmFuZ2UgaXMgbG93ZXIgdGhhbiA4IG1pbGxpb24geWVhcnMKZGltKENldGFjZWFfb2NjW0NldGFjZWFfb2NjJGFnZV9yYW5nZTwxMCxdKQoKZ2dwbG90KENldGFjZWFfb2NjLCBhZXMoeD1hZ2VfcmFuZ2UsIGZpbGw9YWNjZXB0ZWRfcmFuaykpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJBZ2UgdW5jZXJ0YWludHkgcmFuZ2UgKE15KSIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobmFtZSA9ICJOdW1iZXIgb2YgY29ycmVzcG9uZGluZyBvY2N1cnJlbmNlcyIpICsKICBnZW9tX3NlZ21lbnQoYWVzKHggPSA5LjUsIHkgPSAwLCB4ZW5kID0gOS41LCB5ZW5kPTEwNTApLCBjb2xvcj0iYmxhY2siLCBsaW5ldHlwZT0iZGFzaGVkIikgKwogIGdndGl0bGUoIkRpc3RyaWJ1dGlvbiBvZiBvY2N1cnJlbmNlcycgYWdlIHVuY2VydGFpbnR5IHJhbmdlIikKYGBgCgpNb3N0IG9mIG9jY3VycmVuY2VzIHNob3cgbGVzcyB0aGFuIDEwIE15IGFnZSB1bmNlcnRhaW50eSwgbGV0J3MgdHJ5IHRvIGtlZXAgb25seSB0aGVzZSBvbmVzLgoKYGBge3J9CmRhdGEuZnJhbWUoYWxsX3JhbmdlcyA9IGRpbShDZXRhY2VhX29jYylbMV0sCiAgICAgICAgICAgc21hbGxlcl8xME15ID0gZGltKENldGFjZWFfb2NjW0NldGFjZWFfb2NjJGFnZV9yYW5nZTwxMCxdKVsxXSwKICAgICAgICAgICByZW1vdmVkID0gZGltKENldGFjZWFfb2NjKVsxXS1kaW0oQ2V0YWNlYV9vY2NbQ2V0YWNlYV9vY2MkYWdlX3JhbmdlPDEwLF0pWzFdLCByb3cubmFtZXMgPSAiTnVtYmVyIG9mIG9jY3VycmVuY2VzIikKYGBgCgpgYGB7ciBmaWcuaGVpZ2h0PTZ9CmdncGxvdChDZXRhY2VhX29jYywgYWVzKHg9YWdlX3J1bmlmLCB5PWFnZV9yYW5nZSkpICsKICBnZW9tX3BvaW50KGFscGhhPTAuMDUpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJVbmlmb3JtbHkgZHJhd24gYWdlIChNeSkiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKG5hbWUgPSAiQWdlIHVuY2VydGFpbnR5IHJhbmdlIChNeSkiKSArCiAgZ2d0aXRsZSgiRGlzdHJpYnV0aW9uIG9mIG9jY3VycmVuY2VzJyBhZ2UgdW5jZXJ0YWludHkgcmFuZ2UiKQoKZ2dwbG90KENldGFjZWFfb2NjW0NldGFjZWFfb2NjJGFnZV9yYW5nZSAhPSA2My40MTIsXSwgYWVzKHg9YWdlX3J1bmlmLCB5PWFnZV9yYW5nZSkpICsKICBnZW9tX3BvaW50KGFscGhhPTAuMDUpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJVbmlmb3JtbHkgZHJhd24gYWdlIChNeSkiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKG5hbWUgPSAiQWdlIHVuY2VydGFpbnR5IHJhbmdlIChNeSkiKSArCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gMCwgeSA9IDEwLCB4ZW5kPTYwLCB5ZW5kID0gMTApLCBjb2xvcj0iYmxhY2siLCBsaW5ldHlwZT0iZGFzaGVkIikgKwogIGdndGl0bGUoIkRpc3RyaWJ1dGlvbiBvZiBvY2N1cnJlbmNlcycgYWdlIHVuY2VydGFpbnR5IHJhbmdlIikKCmdncGxvdChDZXRhY2VhX29jY1tDZXRhY2VhX29jYyRhZ2VfcmFuZ2U8MTAsXSwgYWVzKHg9YWdlX3J1bmlmLCB5PWFnZV9yYW5nZSkpICsKICBnZW9tX3BvaW50KGFscGhhPTAuMDUpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJVbmlmb3JtbHkgZHJhd24gYWdlIChNeSkiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKG5hbWUgPSAiQWdlIHVuY2VydGFpbnR5IHJhbmdlIChNeSkiKSArCiAgZ2d0aXRsZSgiRGlzdHJpYnV0aW9uIG9mIG9jY3VycmVuY2VzJyBhZ2UgdW5jZXJ0YWludHkgcmFuZ2UiKQoKaGlzdCgtQ2V0YWNlYV9vY2MkYWdlX3J1bmlmLCBicmVha3MgPSA1MCwgY29sPSJyZWQiLCBwcm9iYWJpbGl0eT1ULCBtYWluPSJEaXN0cmlidXRpb24gb2Ygb2NjdXJyZW5jZXMsIHdpdGggKHJlZCkgb2Ygd2l0aG91dCAoYmx1ZSkgcmVjZW50IHNhbXBsZXMiLCB4bGFiID0gIlRpbWUgKE15KSIsIHlsYWIgPSAiUHJvcG9ydGlvbiBvZiBvY2N1cnJlbmNlcyIpCmhpc3QoLUNldGFjZWFfb2NjW0NldGFjZWFfb2NjJGFnZV9yYW5nZTwxMCxdJGFnZV9ydW5pZiwgYnJlYWtzID0gNTAsIGNvbD0iYmx1ZSIsIHByb2JhYmlsaXR5PVQsIGRlbnNpdHk9VCwgYWRkPVQpCmBgYAoKJFx0byQgVGhlIHJlbW92YWwgb2YgaGlnaGx5IHVuY2VydGFpbiBvY2N1cnJlbmNlcyBzZWVtcyB0byBiZSBvbmx5IGEgbGl0dGxlIGJpYXNlZCwgZXZlbiBpZiB1bmNlcnRhaW50eSBnbG9iYWxseSBpbmNyZWFzZXMgd2l0aCBhZ2UuCgpgYGB7ciBmaWcuaGVpZ2h0PTh9Cm15X2JyZWFrcyA8LSBjKDEsMywxMCwzNSwxMDAsbWF4KENldGFjZWFfb2NjJGFjY2VwdGVkX25hbWVfY291bnQpKQoKZ2dwbG90KENldGFjZWFfb2NjWyEoQ2V0YWNlYV9vY2MkYWNjZXB0ZWRfcmFuayAlaW4lIGMoInNwZWNpZXMiLCAiZ2VudXMiLCAiZmFtaWx5IikpICYgQ2V0YWNlYV9vY2MkYWdlX3JhbmdlPDEwLF0sIGFlcyh4PS1tYXhfbWEsIHk9YWNjZXB0ZWRfbmFtZSkpICsKICBnZW9tX3NlZ21lbnQoYWVzKHggPSAtbWF4X21hLCB5ID0gcmVvcmRlcihhY2NlcHRlZF9uYW1lLCAtYWdlX21lYW4pLCB4ZW5kID0gLW1pbl9tYSwgeWVuZD1yZW9yZGVyKGFjY2VwdGVkX25hbWUsIC1hZ2VfbWVhbiksIGNvbG9yPWFjY2VwdGVkX25hbWVfY291bnQpLCBhcnJvdz1hcnJvdyhlbmRzID0gImJvdGgiLCBhbmdsZT05MCwgbGVuZ3RoID0gdW5pdCgxLCAibW0iKSksIGFscGhhPTAuNSkgKwogIGdlb21fcG9pbnQoYWVzKHg9LWFnZV9ydW5pZiksIGNvbD0icmVkIiwgY2V4PTEsIGFscGhhPTAuNSkgKwogIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIlRpbWUgKE15KSIpICsKICBzY2FsZV95X2Rpc2NyZXRlKG5hbWUgPSAiQWNjZXB0ZWQgcmFua3MiKSArCiAgbGFicyhjb2xvdXI9IkFjY2VwdGVkIG5hbWVzIGNvdW50IikgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50bihjb2xvdXJzID0gYygiZGFya2JsdWUiLCAiZm9yZXN0Z3JlZW4iLCAiYmxhY2siKSwgdHJhbnM9ImxvZyIsIGJyZWFrcz1teV9icmVha3MsIGxhYmVscz1teV9icmVha3MpICsgCiAgZ2d0aXRsZSgiRGlzdHJpYnV0aW9ucyBvZiBmb3NzaWwgYWdlIHJhbmdlcywgYnkgYWNjZXB0ZWQgcmFuayIpICsKICBmYWNldF9ncmlkKGFjY2VwdGVkX3JhbmsgfiAuLCBzY2FsZXMgPSAiZnJlZSIpCgpnZ3Bsb3QoQ2V0YWNlYV9vY2NbQ2V0YWNlYV9vY2MkYWNjZXB0ZWRfcmFuayA9PSJzcGVjaWVzIiAmIENldGFjZWFfb2NjJGFnZV9yYW5nZTwxMCxdLCBhZXMoeD0tbWF4X21hLCB5PWFjY2VwdGVkX25hbWUpKSArCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gLW1heF9tYSwgeSA9IHJlb3JkZXIoYWNjZXB0ZWRfbmFtZSwgLWFnZV9tZWFuKSwgeGVuZCA9IC1taW5fbWEsIHllbmQ9cmVvcmRlcihhY2NlcHRlZF9uYW1lLCAtYWdlX21lYW4pLCBjb2xvcj1hY2NlcHRlZF9uYW1lX2NvdW50KSwgYXJyb3c9YXJyb3coZW5kcyA9ICJib3RoIiwgYW5nbGU9OTAsIGxlbmd0aCA9IHVuaXQoMSwgIm1tIikpLCBhbHBoYT0wLjUpICsKICBnZW9tX3BvaW50KGFlcyh4PS1hZ2VfcnVuaWYpLCBjb2w9InJlZCIsIGNleD0xLCBhbHBoYT0wLjUpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJUaW1lIChNeSkiKSArCiAgc2NhbGVfeV9kaXNjcmV0ZShuYW1lID0gIkFnZSByYW5nZXMiKSArCiAgbGFicyhjb2xvdXI9IkFjY2VwdGVkIG5hbWVzIGNvdW50IikgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X3RleHQoc2l6ZT0yKSkgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50bihjb2xvdXJzID0gYygiZGFya2JsdWUiLCAiZm9yZXN0Z3JlZW4iLCAiYmxhY2siKSwgdHJhbnM9ImxvZyIsIGJyZWFrcz1teV9icmVha3MsIGxhYmVscz1teV9icmVha3MpICsgCiAgZ2d0aXRsZSgiRGlzdHJpYnV0aW9ucyBvZiBmb3NzaWwgYWdlIHJhbmdlcyAoc3BlY2llcykiKSArCiAgZmFjZXRfZ3JpZChhY2NlcHRlZF9yYW5rIH4gLiwgc2NhbGVzID0gImZyZWUiKQoKZ2dwbG90KENldGFjZWFfb2NjW0NldGFjZWFfb2NjJGFjY2VwdGVkX3JhbmsgPT0iZ2VudXMiICYgQ2V0YWNlYV9vY2MkYWdlX3JhbmdlPDEwLF0sIGFlcyh4PS1tYXhfbWEsIHk9YWNjZXB0ZWRfbmFtZSkpICsKICBnZW9tX3NlZ21lbnQoYWVzKHggPSAtbWF4X21hLCB5ID0gcmVvcmRlcihhY2NlcHRlZF9uYW1lLCAtYWdlX21lYW4pLCB4ZW5kID0gLW1pbl9tYSwgeWVuZD1yZW9yZGVyKGFjY2VwdGVkX25hbWUsIC1hZ2VfbWVhbiksIGNvbG9yPWFjY2VwdGVkX25hbWVfY291bnQpLCBhcnJvdz1hcnJvdyhlbmRzID0gImJvdGgiLCBhbmdsZT05MCwgbGVuZ3RoID0gdW5pdCgxLCAibW0iKSksIGFscGhhPTAuNSkgKwogIGdlb21fcG9pbnQoYWVzKHg9LWFnZV9ydW5pZiksIGNvbD0icmVkIiwgY2V4PTEsIGFscGhhPTAuNSkgKwogIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIlRpbWUgKE15KSIpICsKICBzY2FsZV95X2Rpc2NyZXRlKG5hbWUgPSAiR2VudXMiKSArCiAgbGFicyhjb2xvdXI9IkFjY2VwdGVkIG5hbWVzIGNvdW50IikgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X3RleHQoc2l6ZT02KSkgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50bihjb2xvdXJzID0gYygiZGFya2JsdWUiLCAiZm9yZXN0Z3JlZW4iLCAiYmxhY2siKSwgdHJhbnM9ImxvZyIsIGJyZWFrcz1teV9icmVha3MsIGxhYmVscz1teV9icmVha3MpICsgCiAgZ2d0aXRsZSgiRGlzdHJpYnV0aW9ucyBvZiBmb3NzaWwgYWdlIHJhbmdlcyAoZ2VuZXJhKSIpICsKICBmYWNldF9ncmlkKGFjY2VwdGVkX3JhbmsgfiAuLCBzY2FsZXMgPSAiZnJlZSIpCgpnZ3Bsb3QoQ2V0YWNlYV9vY2NbQ2V0YWNlYV9vY2MkYWNjZXB0ZWRfcmFuayA9PSJmYW1pbHkiICYgQ2V0YWNlYV9vY2MkYWdlX3JhbmdlPDEwLF0sIGFlcyh4PS1tYXhfbWEsIHk9YWNjZXB0ZWRfbmFtZSkpICsKICBnZW9tX3NlZ21lbnQoYWVzKHggPSAtbWF4X21hLCB5ID0gcmVvcmRlcihhY2NlcHRlZF9uYW1lLCAtYWdlX21lYW4pLCB4ZW5kID0gLW1pbl9tYSwgeWVuZD1yZW9yZGVyKGFjY2VwdGVkX25hbWUsIC1hZ2VfbWVhbiksIGNvbG9yPWFjY2VwdGVkX25hbWVfY291bnQpLCBhcnJvdz1hcnJvdyhlbmRzID0gImJvdGgiLCBhbmdsZT05MCwgbGVuZ3RoID0gdW5pdCgxLCAibW0iKSksIGFscGhhPTAuNSkgKwogIGdlb21fcG9pbnQoYWVzKHg9LWFnZV9ydW5pZiksIGNvbD0icmVkIiwgY2V4PTEsIGFscGhhPTAuNSkgKwogIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIlRpbWUgKE15KSIpICsKICBzY2FsZV95X2Rpc2NyZXRlKG5hbWUgPSAiR2VudXMiKSArCiAgbGFicyhjb2xvdXI9IkFjY2VwdGVkIG5hbWVzIGNvdW50IikgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50bihjb2xvdXJzID0gYygiZGFya2JsdWUiLCAiZm9yZXN0Z3JlZW4iLCAiYmxhY2siKSwgdHJhbnM9ImxvZyIsIGJyZWFrcz1teV9icmVha3MsIGxhYmVscz1teV9icmVha3MpICsgCiAgZ2d0aXRsZSgiRGlzdHJpYnV0aW9ucyBvZiBmb3NzaWwgYWdlIHJhbmdlcyAoZmFtaWxpZXMpIikgKwogIGZhY2V0X2dyaWQoYWNjZXB0ZWRfcmFuayB+IC4sIHNjYWxlcyA9ICJmcmVlIikKYGBgCgokXHRvJCBTb21lIHNwZWNpZXMgKG9yIG90aGVyIHJhbmtzKSBoYXZlIHNldmVyYWwgb2NjdXJyZW5jZXMgd2l0aCBzZXZlcmFsIHRpbWUgcmFuZ2VzLCAqKmxldCdzIGNvbWJpbmUgdGhlbSBpbnRvIGEgdW5pcXVlIHJhbmdlIGNvdmVyaW5nIGFsbCB0aGUgb3RoZXJzKiouCgojIyBDb21iaW5lZCB0aW1lIHJhbmdlcyA9IHVuaXF1ZSB0aW1lIHJhbmdlIGZvciBvY2N1cnJlbmNlcyB3aXRoIHRoZSBzYW1lIG5hbWUgKHdpdGhvdXQgdGhlIGJpZ2dlc3Qgb25lcykKCmBgYHtyIGZpZy5oZWlnaHQ9OCwgd2FybmluZz1GQUxTRX0KIyBHZXQgdGhlIG1pbmltdW4gb2YgdGhlIG1pbmltYWwgYWdlcyBmb3IgZWFjaCBhY2NlcHRlZCBuYW1lCkNldGFjZWFfb2NjJG1pbl9taW5fbWEgPC0gYXBwbHkoQ2V0YWNlYV9vY2MsIDEsIGZ1bmN0aW9uKFgpe21pbihDZXRhY2VhX29jY1tDZXRhY2VhX29jYyRhY2NlcHRlZF9uYW1lPT1YWyJhY2NlcHRlZF9uYW1lIl0gJiBDZXRhY2VhX29jYyRhZ2VfcmFuZ2U8MTAsXSRtaW5fbWEpfSkKIyBHZXQgdGhlIG1heGltdW0gb2YgdGhlIG1heGltYWwgYWdlcyBmb3IgZWFjaCBhY2NlcHRlZCBuYW1lCkNldGFjZWFfb2NjJG1heF9tYXhfbWEgPC0gYXBwbHkoQ2V0YWNlYV9vY2MsIDEsIGZ1bmN0aW9uKFgpe21heChDZXRhY2VhX29jY1tDZXRhY2VhX29jYyRhY2NlcHRlZF9uYW1lPT1YWyJhY2NlcHRlZF9uYW1lIl0gJiBDZXRhY2VhX29jYyRhZ2VfcmFuZ2U8MTAsXSRtYXhfbWEpfSkKIyBHZXQgdGhlIGNvbWJpbmVkIHRpbWUgaW50ZXJ2YWwKQ2V0YWNlYV9vY2MkYWdlX2NvbWJpbmVkX2ludGVydmFsIDwtIG1hcHBseShmdW5jdGlvbihtaW5fbWluX2FnZSwgbWF4X21heF9hZ2Upe3Bhc3RlKCJbIiwtbWF4X21heF9hZ2UsIiwgIiwtbWluX21pbl9hZ2UsIl0iLCBzZXAgPSAiIil9LCBDZXRhY2VhX29jYyRtaW5fbWluX21hLCBDZXRhY2VhX29jYyRtYXhfbWF4X21hKQojIEdldCB0aGUgY29tYmluZWQgdGltZSBpbnRlcnZhbCBtZWFuCkNldGFjZWFfb2NjJGFnZV9jb21iaW5lZF9tZWFuIDwtIChDZXRhY2VhX29jYyRtaW5fbWluX21hICsgQ2V0YWNlYV9vY2MkbWF4X21heF9tYSkvMgojIEdldCB0aGUgZHVyYXRpb24gb2YgdGhlIGNvbWJpbmVkIHRpbWUgaW50ZXJ2YWxzCkNldGFjZWFfb2NjJGFnZV9jb21iaW5lZF9yYW5nZSA8LSBDZXRhY2VhX29jYyRtYXhfbWF4X21hLUNldGFjZWFfb2NjJG1pbl9taW5fbWEKCmdncGxvdChDZXRhY2VhX29jY1shKENldGFjZWFfb2NjJGFjY2VwdGVkX3JhbmsgJWluJSBjKCJzcGVjaWVzIiwgImdlbnVzIiwgImZhbWlseSIpKSAmIENldGFjZWFfb2NjJGFnZV9yYW5nZTwxMCxdLCBhZXMoeD0tbWF4X21hLCB5PWFjY2VwdGVkX25hbWUpKSArCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gLW1heF9tYXhfbWEsIHkgPSByZW9yZGVyKGFjY2VwdGVkX25hbWUsIC1hZ2VfY29tYmluZWRfbWVhbiksIHhlbmQgPSAtbWluX21pbl9tYSwgeWVuZD1yZW9yZGVyKGFjY2VwdGVkX25hbWUsIC1hZ2VfY29tYmluZWRfbWVhbiksIGNvbG9yPWFjY2VwdGVkX25hbWVfY291bnQpLCBhcnJvdz1hcnJvdyhlbmRzID0gImJvdGgiLCBhbmdsZT05MCwgbGVuZ3RoID0gdW5pdCgxLCAibW0iKSksIGFscGhhPTAuNSkgKwogIGdlb21fcG9pbnQoYWVzKHg9LWFnZV9ydW5pZiksIGNvbD0icmVkIiwgY2V4PTEsIGFscGhhPTAuNSkgKwogIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIlRpbWUgKE15KSIpICsKICBzY2FsZV95X2Rpc2NyZXRlKG5hbWUgPSAiQWNjZXB0ZWQgcmFua3MiKSArCiAgbGFicyhjb2xvdXI9IkFjY2VwdGVkIG5hbWVzIGNvdW50IikgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50bihjb2xvdXJzID0gYygiZGFya2JsdWUiLCAiZm9yZXN0Z3JlZW4iLCAiYmxhY2siKSwgdHJhbnM9ImxvZyIsIGJyZWFrcz1teV9icmVha3MsIGxhYmVscz1teV9icmVha3MpICsgCiAgZ2d0aXRsZSgiRGlzdHJpYnV0aW9ucyBvZiBmb3NzaWwgY29tYmluZWQgYWdlIHJhbmdlcywgYnkgYWNjZXB0ZWQgcmFuayIpICsKICBmYWNldF9ncmlkKGFjY2VwdGVkX3JhbmsgfiAuLCBzY2FsZXMgPSAiZnJlZSIpCgpnZ3Bsb3QoQ2V0YWNlYV9vY2NbQ2V0YWNlYV9vY2MkYWNjZXB0ZWRfcmFuayA9PSJzcGVjaWVzIiAmIENldGFjZWFfb2NjJGFnZV9yYW5nZTwxMCxdLCBhZXMoeD0tbWF4X21hLCB5PWFjY2VwdGVkX25hbWUpKSArCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gLW1heF9tYXhfbWEsIHkgPSByZW9yZGVyKGFjY2VwdGVkX25hbWUsIC1hZ2VfY29tYmluZWRfbWVhbiksIHhlbmQgPSAtbWluX21pbl9tYSwgeWVuZD1yZW9yZGVyKGFjY2VwdGVkX25hbWUsIC1hZ2VfY29tYmluZWRfbWVhbiksIGNvbG9yPWFjY2VwdGVkX25hbWVfY291bnQpLCBhcnJvdz1hcnJvdyhlbmRzID0gImJvdGgiLCBhbmdsZT05MCwgbGVuZ3RoID0gdW5pdCgxLCAibW0iKSksIGFscGhhPTAuNSkgKwogIGdlb21fcG9pbnQoYWVzKHg9LWFnZV9ydW5pZiksIGNvbD0icmVkIiwgY2V4PTEsIGFscGhhPTAuNSkgKwogIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIlRpbWUgKE15KSIpICsKICBzY2FsZV95X2Rpc2NyZXRlKG5hbWUgPSAiQWdlIHJhbmdlcyIpICsKICBsYWJzKGNvbG91cj0iQWNjZXB0ZWQgbmFtZXMgY291bnQiKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC55PWVsZW1lbnRfdGV4dChzaXplPTIpKSArCiAgc2NhbGVfY29sb3JfZ3JhZGllbnRuKGNvbG91cnMgPSBjKCJkYXJrYmx1ZSIsICJmb3Jlc3RncmVlbiIsICJibGFjayIpLCB0cmFucz0ibG9nIiwgYnJlYWtzPW15X2JyZWFrcywgbGFiZWxzPW15X2JyZWFrcykgKyAKICBnZ3RpdGxlKCJEaXN0cmlidXRpb25zIG9mIGZvc3NpbCBjb21iaW5lZCBhZ2UgcmFuZ2VzIChzcGVjaWVzKSIpICsKICBmYWNldF9ncmlkKGFjY2VwdGVkX3JhbmsgfiAuLCBzY2FsZXMgPSAiZnJlZSIpCgpnZ3Bsb3QoQ2V0YWNlYV9vY2NbQ2V0YWNlYV9vY2MkYWNjZXB0ZWRfcmFuayA9PSJnZW51cyIgJiBDZXRhY2VhX29jYyRhZ2VfcmFuZ2U8MTAsXSwgYWVzKHg9LW1heF9tYSwgeT1hY2NlcHRlZF9uYW1lKSkgKwogIGdlb21fc2VnbWVudChhZXMoeCA9IC1tYXhfbWF4X21hLCB5ID0gcmVvcmRlcihhY2NlcHRlZF9uYW1lLCAtYWdlX2NvbWJpbmVkX21lYW4pLCB4ZW5kID0gLW1pbl9taW5fbWEsIHllbmQ9cmVvcmRlcihhY2NlcHRlZF9uYW1lLCAtYWdlX2NvbWJpbmVkX21lYW4pLCBjb2xvcj1hY2NlcHRlZF9uYW1lX2NvdW50KSwgYXJyb3c9YXJyb3coZW5kcyA9ICJib3RoIiwgYW5nbGU9OTAsIGxlbmd0aCA9IHVuaXQoMSwgIm1tIikpLCBhbHBoYT0wLjUpICsKICBnZW9tX3BvaW50KGFlcyh4PS1hZ2VfcnVuaWYpLCBjb2w9InJlZCIsIGNleD0xLCBhbHBoYT0wLjUpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJUaW1lIChNeSkiKSArCiAgc2NhbGVfeV9kaXNjcmV0ZShuYW1lID0gIkdlbmVyYSIpICsKICBsYWJzKGNvbG91cj0iQWNjZXB0ZWQgbmFtZXMgY291bnQiKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC55PWVsZW1lbnRfdGV4dChzaXplPTYpKSArCiAgc2NhbGVfY29sb3JfZ3JhZGllbnRuKGNvbG91cnMgPSBjKCJkYXJrYmx1ZSIsICJmb3Jlc3RncmVlbiIsICJibGFjayIpLCB0cmFucz0ibG9nIiwgYnJlYWtzPW15X2JyZWFrcywgbGFiZWxzPW15X2JyZWFrcykgKyAKICBnZ3RpdGxlKCJEaXN0cmlidXRpb25zIG9mIGZvc3NpbCBjb21iaW5lZCBhZ2UgcmFuZ2VzIChnZW5lcmEpIikgKwogIGZhY2V0X2dyaWQoYWNjZXB0ZWRfcmFuayB+IC4sIHNjYWxlcyA9ICJmcmVlIikKCmdncGxvdChDZXRhY2VhX29jY1tDZXRhY2VhX29jYyRhY2NlcHRlZF9yYW5rID09ImZhbWlseSIgJiBDZXRhY2VhX29jYyRhZ2VfcmFuZ2U8MTAsXSwgYWVzKHg9LW1heF9tYSwgeT1hY2NlcHRlZF9uYW1lKSkgKwogIGdlb21fc2VnbWVudChhZXMoeCA9IC1tYXhfbWF4X21hLCB5ID0gcmVvcmRlcihhY2NlcHRlZF9uYW1lLCAtYWdlX2NvbWJpbmVkX21lYW4pLCB4ZW5kID0gLW1pbl9taW5fbWEsIHllbmQ9cmVvcmRlcihhY2NlcHRlZF9uYW1lLCAtYWdlX2NvbWJpbmVkX21lYW4pLCBjb2xvcj1hY2NlcHRlZF9uYW1lX2NvdW50KSwgYXJyb3c9YXJyb3coZW5kcyA9ICJib3RoIiwgYW5nbGU9OTAsIGxlbmd0aCA9IHVuaXQoMSwgIm1tIikpLCBhbHBoYT0wLjUpICsKICBnZW9tX3BvaW50KGFlcyh4PS1hZ2VfcnVuaWYpLCBjb2w9InJlZCIsIGNleD0xLCBhbHBoYT0wLjUpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJUaW1lIChNeSkiKSArCiAgc2NhbGVfeV9kaXNjcmV0ZShuYW1lID0gIkZhbWlsaWVzIikgKwogIGxhYnMoY29sb3VyPSJBY2NlcHRlZCBuYW1lcyBjb3VudCIpICsKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCkpICsKICBzY2FsZV9jb2xvcl9ncmFkaWVudG4oY29sb3VycyA9IGMoImRhcmtibHVlIiwgImZvcmVzdGdyZWVuIiwgImJsYWNrIiksIHRyYW5zPSJsb2ciLCBicmVha3M9bXlfYnJlYWtzLCBsYWJlbHM9bXlfYnJlYWtzKSArIAogIGdndGl0bGUoIkRpc3RyaWJ1dGlvbnMgb2YgZm9zc2lsIGNvbWJpbmVkIGFnZSByYW5nZXMgKGZhbWlsaWVzKSIpICsKICBmYWNldF9ncmlkKGFjY2VwdGVkX3JhbmsgfiAuLCBzY2FsZXMgPSAiZnJlZSIpCmBgYAoKIyMgT2NjdXJyZW5jZSBkZW5zaXR5CiMjIyBEZW5zaXR5IGRpc3RyaWJ1dGlvbnMKCmBgYHtyIGZpZy5oZWlnaHQ9Nn0KIyBHZXQgaW50ZXJ2YWwgZGVuc2l0eSBvZiBvY2N1cnJlbmNlcwpDZXRhY2VhX29jYyRvY2N1cnJlbmNlX2RlbnNpdHkgPC0gQ2V0YWNlYV9vY2MkYWNjZXB0ZWRfbmFtZV9jb3VudC9DZXRhY2VhX29jYyRhZ2VfcmFuZ2UKCmdncGxvdChDZXRhY2VhX29jY1shKENldGFjZWFfb2NjJGFjY2VwdGVkX3JhbmsgJWluJSBjKCJzdWJzcGVjaWVzIiwgImluZnJhb3JkZXIiKSkgJiBDZXRhY2VhX29jYyRhZ2VfcmFuZ2U8MTAsXSwgYWVzKHg9b2NjdXJyZW5jZV9kZW5zaXR5LCBmaWxsPWZhY3RvcihhY2NlcHRlZF9uYW1lX2NvdW50KSkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aD0wLjEpICsKICBzY2FsZV94X2NvbnRpbnVvdXModHJhbnM9ImxvZzEwIiwgbmFtZT0iRGVuc2l0eSBvZiBvY2N1cnJlbmNlcyAobnVtYmVyL015KSIpICsKICBzY2FsZV9maWxsX2Rpc2NyZXRlKG5hbWU9IkFjY2VwdGVkIG5hbWUgY291bnQiKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpKSArCiAgZ2d0aXRsZSgiRGlzdHJpYnV0aW9ucyBvY2N1cnJlbmNlIGRlbnNpdHksIGJ5IGFjY2VwdGVkIHJhbmsiKSArCiAgZmFjZXRfZ3JpZChhY2NlcHRlZF9yYW5rIH4gLiwgc2NhbGVzID0gImZyZWUiKQpgYGAKCiRcdG8kIERlbnNpdHkgbG9naWNhbGx5IGluY3JlYXNlcyBhcyB0YXhhIHJhbmtzIGluY3JlYXNlLgoKIyMgQ29ycmVsYXRpb24gYmV0d2VlbiB0aW1lIHJhbmdlIGFuZCBhZ2UKCklmIHdlIHdhbnQgdG8gY29ycmVjdCBzcGVjaWVzIGFidW5kYW5jZSBkaWZmZXJlbmNlcyBiYXNlZCBvbiB0aGUgbnVtYmVyIG9mIG9jY3VycmVuY2VzIGluIHRoZSB0aW1lIHJhbmdlICgiZGVuc2l0eSIpLCB0aG9zZSBmYWN0b3JzIHNob3VsZCBub3QgZGVwZW5kIG9uIHRpbWUgaW4gb3JkZXIgdG8gYXZvaWQgcGVuYWxpemluZyBwZXJpb2RzIHdpdGggaGlnaGVyIGRlbnNpdGllcy4KCmBgYHtyfQpjb25kaXRpb25zIDwtIENldGFjZWFfb2NjJGFjY2VwdGVkX3JhbmsgPT0ic3BlY2llcyIgJiBDZXRhY2VhX29jYyRhZ2VfcmFuZ2U8MTAKCiMgS2VlcCBvbmx5IG9uZSBwb2ludCBieSBpZGVudGljYWwgdGltZSBpbnRlcnZhbAoKYWdlX2ludGVydmFsX3RhYmxlIDwtIHRhYmxlKENldGFjZWFfb2NjW2NvbmRpdGlvbnMsXSRhZ2VfaW50ZXJ2YWwpCgppbnRlcnZhbF9tZWFuX2FnZSA8LSBzYXBwbHkobmFtZXMoYWdlX2ludGVydmFsX3RhYmxlKSwgZnVuY3Rpb24oeCl7Q2V0YWNlYV9vY2NbY29uZGl0aW9ucyAmIENldGFjZWFfb2NjJGFnZV9pbnRlcnZhbD09eCxdJGFnZV9tZWFuWzFdfSkKCmludGVydmFsX3JhbmdlIDwtIHNhcHBseShuYW1lcyhhZ2VfaW50ZXJ2YWxfdGFibGUpLCBmdW5jdGlvbih4KXtDZXRhY2VhX29jY1tjb25kaXRpb25zICYgQ2V0YWNlYV9vY2MkYWdlX2ludGVydmFsPT14LF0kYWdlX3JhbmdlWzFdfSkKCmRmIDwtIGRhdGEuZnJhbWUoeD1pbnRlcnZhbF9tZWFuX2FnZSwKICAgICAgICAgICAgICAgICB5PWludGVydmFsX3JhbmdlKQoKZ2dwbG90KGRmLCBhZXMoeD14LCB5PXkpKSArIAogIGdlb21fcG9pbnQoYWxwaGE9MC41KSArCiAgZ2VvbV9zbW9vdGgoZm9ybXVsYSA9IHl+eCwgc3BhbiA9IDAuOSwgbWV0aG9kID0gJ2xvZXNzJykgKwogIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIlRpbWUgKE15KSIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobmFtZSA9ICJVbmNlcnRhaW50eSByYW5nZSIpICsKICBnZ3RpdGxlKCJTbW9vdGhlZCBjb3JyZXNwb25kYW5jZSBiZXR3ZWVuIHRpbWUgcmFuZ2UgYW5kIGFnZSIpCgojIEtlZXAgb25seSBvbmUgcG9pbnQgYnkgaWRlbnRpY2FsIGNvbWJpbmVkIHRpbWUgaW50ZXJ2YWwKYWdlX2NvbWJpbmVkX2ludGVydmFsX3RhYmxlIDwtIHRhYmxlKENldGFjZWFfb2NjW2NvbmRpdGlvbnMsXSRhZ2VfY29tYmluZWRfaW50ZXJ2YWwpCgpjb21iaW5lZF9pbnRlcnZhbF9tZWFuX2FnZSA8LSBzYXBwbHkobmFtZXMoYWdlX2NvbWJpbmVkX2ludGVydmFsX3RhYmxlKSwgZnVuY3Rpb24oeCl7Q2V0YWNlYV9vY2NbY29uZGl0aW9ucyAmIENldGFjZWFfb2NjJGFnZV9jb21iaW5lZF9pbnRlcnZhbD09eCxdJGFnZV9jb21iaW5lZF9tZWFuWzFdfSkKCmNvbWJpbmVkX2ludGVydmFsX3JhbmdlIDwtIHNhcHBseShuYW1lcyhhZ2VfY29tYmluZWRfaW50ZXJ2YWxfdGFibGUpLCBmdW5jdGlvbih4KXtDZXRhY2VhX29jY1tjb25kaXRpb25zICYgQ2V0YWNlYV9vY2MkYWdlX2NvbWJpbmVkX2ludGVydmFsPT14LF0kYWdlX2NvbWJpbmVkX3JhbmdlWzFdfSkKCmNvbWJpbmVkX2RmIDwtIGRhdGEuZnJhbWUoeD1jb21iaW5lZF9pbnRlcnZhbF9tZWFuX2FnZSwKICAgICAgICAgICAgICAgICAgICAgICAgICB5PWNvbWJpbmVkX2ludGVydmFsX3JhbmdlKQoKZ2dwbG90KGNvbWJpbmVkX2RmLCBhZXMoeD14LCB5PXkpKSArIAogIGdlb21fcG9pbnQoYWxwaGE9MC41KSArCiAgZ2VvbV9zbW9vdGgoZm9ybXVsYSA9IHl+eCwgc3BhbiA9IDAuOSwgbWV0aG9kID0gJ2xvZXNzJykgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJUaW1lIChNeSkiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKG5hbWUgPSAiQ29tYmluZWQgdW5jZXJ0YWludHkgcmFuZ2UiKSArCiAgZ2d0aXRsZSgiU21vb3RoZWQgY29ycmVzcG9uZGFuY2UgYmV0d2VlbiBjb21iaW5lZCB0aW1lIHJhbmdlIGFuZCBhZ2UiKQpgYGAKCiRcdG8kIEl0IHNlZW1zIHRoYXQgYWdlIHJhbmdlIHZhcmllcyBpbXBvcnRhbnRseSB3aXRoIHRpbWUsIGJ1dCB3aGVuIHRha2luZyB0aGUgZnVsbCBjb21iaW5lZCByYW5nZSBpbnRvIGFjY291bnQgdGhlIGNvcnJlbGF0aW9uIHNlZW1zIHF1aXRlIHdlYWsgYWZ0ZXIgdGhlIGZpcnN0IG1pbGxpb24geWVhcnMuCgpMZXQncyBsb29rIGF0IHRoZSBkZW5zaXR5IGRpcmVjdGx5LCBiZWNhdXNlIHRoaXMgaXMgd2hhdCBpcyBpbnRlcmVzdGluZyB1cyBkaXJlY3RseS4KCmBgYHtyfQpjb25kaXRpb25zIDwtIENldGFjZWFfb2NjJGFjY2VwdGVkX3JhbmsgPT0ic3BlY2llcyIgJiBDZXRhY2VhX29jYyRhZ2VfcmFuZ2U8MTAKCiMgRnVuY3Rpb24gdG8gcGxvdCBsaW5lYXIgcmVncmVzc2lvbiBjb2VmZmljaWVudHMKbG1fZXFuIDwtIGZ1bmN0aW9uKGRmKXsKICAgIG0gPC0gbG0oeSB+IHgsIGRmKTsKICAgIGVxIDwtIHN1YnN0aXR1dGUoaXRhbGljKHkpID09IGEgKyBiICUuJSBpdGFsaWMoeCkqIiwifn5pdGFsaWMocileMn4iPSJ+cjIsIAogICAgICAgICBsaXN0KGEgPSBmb3JtYXQodW5uYW1lKGNvZWYobSlbMV0pLCBkaWdpdHMgPSAyKSwKICAgICAgICAgICAgICBiID0gZm9ybWF0KHVubmFtZShjb2VmKG0pWzJdKSwgZGlnaXRzID0gMiksCiAgICAgICAgICAgICByMiA9IGZvcm1hdChzdW1tYXJ5KG0pJHIuc3F1YXJlZCwgZGlnaXRzID0gMykpKQogICAgYXMuY2hhcmFjdGVyKGFzLmV4cHJlc3Npb24oZXEpKTsKfQoKIyBLZWVwIG9ubHkgb25lIHBvaW50IGJ5IGlkZW50aWNhbCB0aW1lIGludGVydmFsCmFnZV9pbnRlcnZhbF90YWJsZSA8LSB0YWJsZShDZXRhY2VhX29jY1tjb25kaXRpb25zLF0kYWdlX2ludGVydmFsKQoKaW50ZXJ2YWxfbWVhbl9hZ2UgPC0gc2FwcGx5KG5hbWVzKGFnZV9pbnRlcnZhbF90YWJsZSksIGZ1bmN0aW9uKHgpe0NldGFjZWFfb2NjW2NvbmRpdGlvbnMgJiBDZXRhY2VhX29jYyRhZ2VfaW50ZXJ2YWw9PXgsXSRhZ2VfbWVhblsxXX0pCgppbnRlcnZhbF9kZW5zaXR5IDwtIHNhcHBseShuYW1lcyhhZ2VfaW50ZXJ2YWxfdGFibGUpLCBmdW5jdGlvbih4KXtDZXRhY2VhX29jY1tjb25kaXRpb25zICYgQ2V0YWNlYV9vY2MkYWdlX2ludGVydmFsPT14LF0kb2NjdXJyZW5jZV9kZW5zaXR5WzFdfSkKCmRmX2RlbnNpdHkgPC0gZGF0YS5mcmFtZSh4PWludGVydmFsX21lYW5fYWdlLAogICAgICAgICAgICAgICAgICAgICAgICAgeT1pbnRlcnZhbF9kZW5zaXR5KQoKZ2dwbG90KGRmX2RlbnNpdHksIGFlcyh4PXgsIHk9eSkpICsgCiAgZ2VvbV9wb2ludChhbHBoYT0wLjUpICsKICBnZW9tX3Ntb290aChmb3JtdWxhID0geX54LCBtZXRob2Q9bG0pICsgCiAgc2NhbGVfeF9jb250aW51b3VzKG5hbWUgPSAiVGltZSAoTXkpIikgKwogIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gIkNvbWJpbmVkIGRlbnNpdHkiKSArCiAgZ2d0aXRsZSgiQ29ycmVsYXRpb24gYmV0d2VlbiBkZW5zaXR5IGFuZCBhZ2UiKSArCiAgZ2VvbV90ZXh0KHggPSAzNSwgeSA9IDI1LCBsYWJlbCA9IGxtX2VxbihkZl9kZW5zaXR5KSwgcGFyc2UgPSBUUlVFKQoKIyBLZWVwIG9ubHkgb25lIHBvaW50IGJ5IGlkZW50aWNhbCBjb21iaW5lZCB0aW1lIGludGVydmFsCmFnZV9jb21iaW5lZF9pbnRlcnZhbF90YWJsZSA8LSB0YWJsZShDZXRhY2VhX29jY1tjb25kaXRpb25zLF0kYWdlX2NvbWJpbmVkX2ludGVydmFsKQoKY29tYmluZWRfaW50ZXJ2YWxfbWVhbl9hZ2UgPC0gc2FwcGx5KG5hbWVzKGFnZV9jb21iaW5lZF9pbnRlcnZhbF90YWJsZSksIGZ1bmN0aW9uKHgpe0NldGFjZWFfb2NjW2NvbmRpdGlvbnMgJiBDZXRhY2VhX29jYyRhZ2VfY29tYmluZWRfaW50ZXJ2YWw9PXgsXSRhZ2VfY29tYmluZWRfbWVhblsxXX0pCgpDZXRhY2VhX29jYyRvY2N1cnJlbmNlX2NvbWJpbmVkX2RlbnNpdHkgPC0gQ2V0YWNlYV9vY2MkYWNjZXB0ZWRfbmFtZV9jb3VudC9DZXRhY2VhX29jYyRhZ2VfY29tYmluZWRfcmFuZ2UKCmNvbWJpbmVkX2ludGVydmFsX2RlbnNpdHkgPC0gc2FwcGx5KG5hbWVzKGFnZV9jb21iaW5lZF9pbnRlcnZhbF90YWJsZSksIGZ1bmN0aW9uKHgpe0NldGFjZWFfb2NjW2NvbmRpdGlvbnMgJiBDZXRhY2VhX29jYyRhZ2VfY29tYmluZWRfaW50ZXJ2YWw9PXgsXSRvY2N1cnJlbmNlX2NvbWJpbmVkX2RlbnNpdHlbMV19KQoKY29tYmluZWRfZGZfZGVuc2l0eSA8LSBkYXRhLmZyYW1lKHg9Y29tYmluZWRfaW50ZXJ2YWxfbWVhbl9hZ2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5PWNvbWJpbmVkX2ludGVydmFsX2RlbnNpdHkpCgpnZ3Bsb3QoY29tYmluZWRfZGZfZGVuc2l0eSwgYWVzKHg9eCwgeT15KSkgKyAKICBnZW9tX3BvaW50KGFscGhhPTAuNSkgKwogIGdlb21fc21vb3RoKGZvcm11bGEgPSB5fngsIG1ldGhvZD1sbSkgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJUaW1lIChNeSkiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKG5hbWUgPSAiQ29tYmluZWQgZGVuc2l0eSIpICsKICBnZ3RpdGxlKCJDb3JyZWxhdGlvbiBiZXR3ZWVuIGNvbWJpbmVkIGRlbnNpdHkgYW5kIGFnZSIpICsKICBnZW9tX3RleHQoeCA9IDE1LCB5ID0gNiwgbGFiZWwgPSBsbV9lcW4oY29tYmluZWRfZGZfZGVuc2l0eSksIHBhcnNlID0gVFJVRSkKYGBgCgokXHRvJCBUaGUgZGVuc2l0eSBiYXNlZCBvbiBjb21iaW5lZCByYW5nZXMgaXMgbXVjaCBsZXNzIHRpbWUtZGVwZW5kYW50IHRoYW4gdGhlIGRlbnNpdHkgYmFzZWQgb24gaW5pdGlhbCByYW5nZSBhZ2VzLiBXZSB3aWxsIHRoZXJlZm9yZSB1c2UgdGhlIGNvbWJpbmVkIGRlbnNpdHkgZm9yIG91ciBjb3JyZWN0aW9ucy4KCiMjIFN1Yi1zYW1wbGluZyBvZiBvY2N1cnJlbmNlcyB3aXRoIGEgbm9ybWFsaXplZCBkZW5zaXR5IGFsb25nIHRoZSBjb21iaW5lZCByYW5nZXMKIyMjIENvbXBhcmUgZGVuc2l0aWVzIGZvciBzaW5nbGUgdnMuIGNvbWJpbmVkIHJhbmdlcy4KCmBgYHtyIGZpZy5oZWlnaHQ9Nn0KY29uZGl0aW9ucyA8LSAhKENldGFjZWFfb2NjJGFjY2VwdGVkX3JhbmsgJWluJSBjKCJzdWJzcGVjaWVzIiwgImluZnJhb3JkZXIiKSkgJiBDZXRhY2VhX29jYyRhZ2VfcmFuZ2U8MTAKCmdncGxvdChDZXRhY2VhX29jY1tjb25kaXRpb25zLF0sIGFlcyh4PW9jY3VycmVuY2VfZGVuc2l0eSwgZmlsbD1mYWN0b3IoYWNjZXB0ZWRfbmFtZV9jb3VudCkpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGg9MC4xKSArCiAgc2NhbGVfeF9jb250aW51b3VzKHRyYW5zPSJsb2cxMCIsIG5hbWU9IkRlbnNpdHkgb2Ygb2NjdXJyZW5jZXMgKG51bWJlci9NeSkiKSArCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lPSJBY2NlcHRlZCBuYW1lIGNvdW50IikgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIGdndGl0bGUoIkRpc3RyaWJ1dGlvbnMgb2Ygb2NjdXJyZW5jZSBkZW5zaXR5LCBieSBhY2NlcHRlZCByYW5rIikgKwogIGZhY2V0X2dyaWQoYWNjZXB0ZWRfcmFuayB+IC4sIHNjYWxlcyA9ICJmcmVlIikKCmdncGxvdChDZXRhY2VhX29jY1tjb25kaXRpb25zLF0sIGFlcyh4PW9jY3VycmVuY2VfY29tYmluZWRfZGVuc2l0eSwgZmlsbD1mYWN0b3IoYWNjZXB0ZWRfbmFtZV9jb3VudCkpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGg9MC4wNSkgKwogIHNjYWxlX3hfY29udGludW91cyh0cmFucz0ibG9nMTAiLCBuYW1lPSJDb21iaW5lZCBkZW5zaXR5IG9mIG9jY3VycmVuY2VzIChudW1iZXIvTXkpIikgKwogIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZT0iQWNjZXB0ZWQgbmFtZSBjb3VudCIpICsKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCkpICsKICBnZ3RpdGxlKCJEaXN0cmlidXRpb25zIG9mIGNvbWJpbmVkIG9jY3VycmVuY2UgZGVuc2l0eSwgYnkgYWNjZXB0ZWQgcmFuayIpICsKICBmYWNldF9ncmlkKGFjY2VwdGVkX3JhbmsgfiAuLCBzY2FsZXMgPSAiZnJlZSIpCmBgYAoKJFx0byQgRGVuc2l0aWVzIGFyZSBzbWFsbGVyIGFuZCBtb3JlIGNvbmNlbnRyYXRlZCB3aXRoIHRoZSBjb21iaW5lZCByYW5nZXMgKGxhcmdlciB0aW1lIHNwYW4gKyBsZXNzIHJhbmdlcyBpbiB0b3RhbCBiZWNhdXNlIG9mIHRoZSBjb2xsZXBzZXMgaW50byB1bmlxdWUgcmFuZ2VzKS4KCiMjIyBDb21wYXJlIGRlbnNpdGllcyBieSBhY2NlcHRlZCBuYW1lIGNvdW50IChzcGVjaWVzIG9ubHkpCgpMZXQncyBmb2N1cyBub3cgb24gdGhlIG9jY3VycmVuY2VzIGFjY2VwdGVkIGF0IHRoZSBzcGVjaWVzIGxldmVsIGJlY2F1c2UgdGhleSBhcmUgdGhlIG9uZSBmb3Igd2hpY2ggd2UgY2FuIGNvcnJlY3QgdGhlIGFidW5kYW5jZSBiaWFzIGJ5IHN1YnNhbXBsaW5nIHRoZSBtb3N0IGNvbmNlbnRyYXRlZCBjb21iaW5lZCBpbnRlcnZhbHMuCgpgYGB7ciBmaWcuaGVpZ2h0PTZ9CmNvbmRpdGlvbnMgPC0gQ2V0YWNlYV9vY2MkYWNjZXB0ZWRfcmFuayA9PSJzcGVjaWVzIiAmIENldGFjZWFfb2NjJGFnZV9yYW5nZTwxMAoKZ2dwbG90KENldGFjZWFfb2NjW2NvbmRpdGlvbnMsXSwgYWVzKHg9b2NjdXJyZW5jZV9kZW5zaXR5LCBmaWxsPWZhY3RvcihhY2NlcHRlZF9uYW1lX2NvdW50KSkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aD0wLjEpICsKICBzY2FsZV94X2NvbnRpbnVvdXModHJhbnM9ImxvZzEwIiwgbmFtZT0iRGVuc2l0eSBvZiBvY2N1cnJlbmNlcyAobnVtYmVyL015KSIpICsKICBzY2FsZV9maWxsX2Rpc2NyZXRlKG5hbWU9IkFjY2VwdGVkIG5hbWUgY291bnQiKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpKSArCiAgZ2d0aXRsZSgiRGlzdHJpYnV0aW9ucyBvZiBvY2N1cnJlbmNlIGRlbnNpdHkgYW1vbmcgc3BlY2llcyIpICsKICBmYWNldF9ncmlkKGFjY2VwdGVkX25hbWVfY291bnQgfiAuLCBzY2FsZXMgPSAiZnJlZSIpCgpnZ3Bsb3QoQ2V0YWNlYV9vY2NbY29uZGl0aW9ucyxdLCBhZXMoeD1vY2N1cnJlbmNlX2NvbWJpbmVkX2RlbnNpdHksIGZpbGw9ZmFjdG9yKGFjY2VwdGVkX25hbWVfY291bnQpKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoPTAuMDUpICsKICBzY2FsZV94X2NvbnRpbnVvdXModHJhbnM9ImxvZzEwIiwgbmFtZT0iQ29tYmluZWQgZGVuc2l0eSBvZiBvY2N1cnJlbmNlcyAobnVtYmVyL015KSIpICsKICBzY2FsZV9maWxsX2Rpc2NyZXRlKG5hbWU9IkFjY2VwdGVkIG5hbWUgY291bnQiKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpKSArCiAgZ2d0aXRsZSgiRGlzdHJpYnV0aW9ucyBvZiBjb21iaW5lZCBvY2N1cnJlbmNlIGRlbnNpdHkgYW1vbmcgc3BlY2llcyIpICsKICBmYWNldF9ncmlkKGFjY2VwdGVkX25hbWVfY291bnQgfiAuLCBzY2FsZXMgPSAiZnJlZSIpCmBgYAoKJFx0byQgVGhlaXIgaXMgYSBodWdlIHNwYW4gb2YgZGVuc2l0aWVzIGRyaXZlbiBieSB0aGUgbnVtYmVyIG9mIG9jY3VycmVuY2VzIGZvciB0aGUgc2FtZSBzcGVjaWVzIHRoYXQgd2UgY2FuIHJlZHVjZSBieSBzdWJzYW1wbGluZyB0aGUgbW9zdCBjb25jZW50cmF0ZWQgaW50ZXJ2YWxzLgoKIyMjIEltcGFjdCBvZiBjb3JyZWN0aW5nIHN1YnNhbXBsaW5nIG9uIGRlbnNpdHkgZGlzdHJpYnV0aW9ucyAoc3BlY2llcyBvbmx5KQoKYGBge3IgZmlnLmhlaWdodD02fQpjb25kaXRpb25zIDwtIENldGFjZWFfb2NjJGFjY2VwdGVkX3JhbmsgPT0ic3BlY2llcyIgJiBDZXRhY2VhX29jYyRhZ2VfcmFuZ2U8MTAKCmdncGxvdChDZXRhY2VhX29jY1tjb25kaXRpb25zLF0sIGFlcyh4PW9jY3VycmVuY2VfY29tYmluZWRfZGVuc2l0eSwgZmlsbD1mYWN0b3IoYWNjZXB0ZWRfbmFtZV9jb3VudCkpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGg9MC4wNSkgKwogIHNjYWxlX3hfY29udGludW91cyh0cmFucz0ibG9nMTAiLCBuYW1lPSJDb21iaW5lZCBkZW5zaXR5IG9mIG9jY3VycmVuY2VzIChudW1iZXIvTXkpIikgKwogIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZT0iQWNjZXB0ZWQgbmFtZSBjb3VudCIpICsKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCkpICsKICBnZ3RpdGxlKHBhc3RlKCJEaXN0cmlidXRpb25zIG9mIGNvbWJpbmVkIG9jY3VycmVuY2UgZGVuc2l0eSBhbW9uZyBzcGVjaWVzIChuID0gIiwgZGltKENldGFjZWFfb2NjW2NvbmRpdGlvbnMsXSlbMV0sICIpIiwgc2VwPSIiKSkgKwogIGZhY2V0X2dyaWQoYWNjZXB0ZWRfbmFtZV9jb3VudCB+IC4sIHNjYWxlcyA9ICJmcmVlIikKCiMgQWRkIGF0IGxlYXN0IG9uZSBvY2N1cnJlbmNlIG9mIGVhY2ggc3BlY2llcwpDZXRhY2VhX29jY19zYW1wbGVkIDwtIGMoKQpDZXRhY2VhX29jY19ub3RzYW1wbGVkIDwtIGMoKQpmb3IgKGkgaW4gYXMubnVtZXJpYyhyb3cubmFtZXMoQ2V0YWNlYV9vY2NbY29uZGl0aW9ucyxdKSkpewogIHJvdyA8LSBDZXRhY2VhX29jY1thcy5jaGFyYWN0ZXIoaSksXQogIGlmICghKHJvdyRhY2NlcHRlZF9uYW1lICVpbiUgQ2V0YWNlYV9vY2Nfc2FtcGxlZCRhY2NlcHRlZF9uYW1lKSl7CiAgICBDZXRhY2VhX29jY19zYW1wbGVkIDwtIHJiaW5kKENldGFjZWFfb2NjX3NhbXBsZWQsIHJvdykKICB9ZWxzZXsKICAgIENldGFjZWFfb2NjX25vdHNhbXBsZWQgPC0gcmJpbmQoQ2V0YWNlYV9vY2Nfbm90c2FtcGxlZCwgcm93KQogIH0KfQoKIyBBZGQgb2NjdXJyZW5jZXMgaW4gdGhlIHJlbWFuaW5nIG9uZXMsIGJ5IHVuZGVyd2VpZ2h0aW5nIGRlbnNlIHNwZWNpZXMKQ2V0YWNlYV9vY2Nfc2FtcGxlZCA8LSByYmluZChDZXRhY2VhX29jY19zYW1wbGVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbihDZXRhY2VhX29jY19ub3RzYW1wbGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZT04MDAtZGltKENldGFjZWFfb2NjX3NhbXBsZWQpWzFdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3ZWlnaHQ9MS9DZXRhY2VhX29jY19ub3RzYW1wbGVkJG9jY3VycmVuY2VfY29tYmluZWRfZGVuc2l0eSoqMykpCgpDZXRhY2VhX29jY19zYW1wbGVkJG1pbl9taW5fbWEgPC0gYXBwbHkoQ2V0YWNlYV9vY2Nfc2FtcGxlZCwgMSwgZnVuY3Rpb24oWCl7bWluKENldGFjZWFfb2NjX3NhbXBsZWRbQ2V0YWNlYV9vY2Nfc2FtcGxlZCRhY2NlcHRlZF9uYW1lPT1YWyJhY2NlcHRlZF9uYW1lIl0sXSRtaW5fbWEpfSkKQ2V0YWNlYV9vY2Nfc2FtcGxlZCRtYXhfbWF4X21hIDwtIGFwcGx5KENldGFjZWFfb2NjX3NhbXBsZWQsIDEsIGZ1bmN0aW9uKFgpe21heChDZXRhY2VhX29jY19zYW1wbGVkW0NldGFjZWFfb2NjX3NhbXBsZWQkYWNjZXB0ZWRfbmFtZT09WFsiYWNjZXB0ZWRfbmFtZSJdLF0kbWF4X21hKX0pCkNldGFjZWFfb2NjX3NhbXBsZWQkYWdlX2NvbWJpbmVkX3JhbmdlIDwtIENldGFjZWFfb2NjX3NhbXBsZWQkbWF4X21heF9tYS1DZXRhY2VhX29jY19zYW1wbGVkJG1pbl9taW5fbWEKQ2V0YWNlYV9vY2Nfc2FtcGxlZCRhY2NlcHRlZF9uYW1lX2NvdW50IDwtIHNhcHBseShDZXRhY2VhX29jY19zYW1wbGVkJGFjY2VwdGVkX25hbWUsIGZ1bmN0aW9uKHgpe3RhYmxlKENldGFjZWFfb2NjX3NhbXBsZWQkYWNjZXB0ZWRfbmFtZSlbeF19KQpDZXRhY2VhX29jY19zYW1wbGVkJG9jY3VycmVuY2VfY29tYmluZWRfZGVuc2l0eSA8LSBDZXRhY2VhX29jY19zYW1wbGVkJGFjY2VwdGVkX25hbWVfY291bnQvQ2V0YWNlYV9vY2Nfc2FtcGxlZCRhZ2VfY29tYmluZWRfcmFuZ2UKCgpnZ3Bsb3QoQ2V0YWNlYV9vY2Nfc2FtcGxlZCwgYWVzKHg9b2NjdXJyZW5jZV9jb21iaW5lZF9kZW5zaXR5LCBmaWxsPWZhY3RvcihhY2NlcHRlZF9uYW1lX2NvdW50KSkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aD0wLjA1KSArCiAgc2NhbGVfeF9jb250aW51b3VzKHRyYW5zPSJsb2cxMCIsIG5hbWU9IkNvbWJpbmVkIGRlbnNpdHkgb2Ygb2NjdXJyZW5jZXMgKG51bWJlci9NeSkiLCBsaW1pdHM9YygwLjEsIDEwMDApKSArCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lPSJBY2NlcHRlZCBuYW1lIGNvdW50IikgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIGdndGl0bGUocGFzdGUoIkRpc3RyaWJ1dGlvbnMgb2YgY29tYmluZWQgb2NjdXJyZW5jZSBkZW5zaXR5IGFtb25nIHNwZWNpZXMsIGFmdGVyIHNhbXBsaW5nIChuID0gIiwgZGltKENldGFjZWFfb2NjX3NhbXBsZWQpWzFdLCAiKSIsIHNlcD0iIikpICsKICBmYWNldF9ncmlkKGFjY2VwdGVkX25hbWVfY291bnQgfiAuLCBzY2FsZXMgPSAiZnJlZSIpCmBgYAoKJFx0byQgU3Vic2FtcGxpbmcgc3VjY2Vzc2Z1bGx5IHJlZHVjZXMgdGhlIGRlbnNpdHkgc3BhbiBmcm9tIDIgdG8gMSBvcmRlciBvZiBtYWduaXR1ZGUuCgojIyMgSW1wYWN0IG9mIHN1YnNhbXBsaW5nIG9uIG9jY3VycmVuY2VzIHJlcGFydGl0aW9uIChzcGVjaWVzIG9ubHkpCgpTZWUgd2hhdCBvdXIgZGlzdHJpYnV0aW9ucyBsb29vayBsaWtlIGFmdGVyIHN1YnNhbXBsaW5nIDoKCmBgYHtyIGZpZy5oZWlnaHQ9NX0KYnJlYWtzIDwtIGMoMC4xMjUsMC4yNSwwLjUsMSwyLDQsOCwxNikKCmdncGxvdChDZXRhY2VhX29jY1tDZXRhY2VhX29jYyRhY2NlcHRlZF9yYW5rID09InNwZWNpZXMiICYgQ2V0YWNlYV9vY2MkYWdlX3JhbmdlPDEwLF0sIGFlcyh4PS1tYXhfbWEsIHk9YWNjZXB0ZWRfbmFtZSkpICsKICBnZW9tX3NlZ21lbnQoYWVzKHggPSAtbWF4X21heF9tYSwgeSA9IHJlb3JkZXIoYWNjZXB0ZWRfbmFtZSwgLWFnZV9jb21iaW5lZF9tZWFuKSwgeGVuZCA9IC1taW5fbWluX21hLCB5ZW5kPXJlb3JkZXIoYWNjZXB0ZWRfbmFtZSwgLWFnZV9jb21iaW5lZF9tZWFuKSwgY29sb3I9b2NjdXJyZW5jZV9jb21iaW5lZF9kZW5zaXR5KSwgYXJyb3c9YXJyb3coZW5kcyA9ICJib3RoIiwgYW5nbGU9OTAsIGxlbmd0aCA9IHVuaXQoMSwgIm1tIikpLCBhbHBoYT0wLjUpICsKICBnZW9tX3BvaW50KGFlcyh4PS1hZ2VfcnVuaWYpLCBjb2w9InJlZCIsIGNleD0wLjUsIGFscGhhPTAuNSkgKwogIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIlRpbWUgKE15KSIpICsKICBzY2FsZV95X2Rpc2NyZXRlKG5hbWUgPSAiU3BlY2llcyIpICsKICBsYWJzKGNvbG91cj0iT2NjdXJyZW5jZVxuZGVuc2l0eSIpICsKICB0aGVtZShheGlzLnRleHQueT1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy55PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCkpICsKICBzY2FsZV9jb2xvcl9ncmFkaWVudG4oY29sb3VycyA9IGMoImRhcmtibHVlIiwgImZvcmVzdGdyZWVuIiwgImJsYWNrIiksIHRyYW5zPSJsb2ciLCBicmVha3M9YnJlYWtzLCBsYWJlbHM9YnJlYWtzKSArIAogIGdndGl0bGUocGFzdGUoIkRpc3RyaWJ1dGlvbnMgb2Ygc3BlY2llcyBmb3NzaWwgYWdlIHJhbmdlcywgYmVmb3JlIGNvcnJlY3Rpbmcgc2FtcGxpbmcgKG4gPSAiLCBkaW0oQ2V0YWNlYV9vY2NbQ2V0YWNlYV9vY2MkYWNjZXB0ZWRfcmFuayA9PSJzcGVjaWVzIiAmIENldGFjZWFfb2NjJGFnZV9yYW5nZTwxMCxdKVsxXSwgIikiLCBzZXA9IiIpKQoKZ2dwbG90KENldGFjZWFfb2NjX3NhbXBsZWQsIGFlcyh4PS1tYXhfbWEsIHk9YWNjZXB0ZWRfbmFtZSkpICsKICBnZW9tX3NlZ21lbnQoYWVzKHggPSAtbWF4X21heF9tYSwgeSA9IHJlb3JkZXIoYWNjZXB0ZWRfbmFtZSwgLWFnZV9jb21iaW5lZF9tZWFuKSwgeGVuZCA9IC1taW5fbWluX21hLCB5ZW5kPXJlb3JkZXIoYWNjZXB0ZWRfbmFtZSwgLWFnZV9jb21iaW5lZF9tZWFuKSwgY29sb3I9b2NjdXJyZW5jZV9jb21iaW5lZF9kZW5zaXR5KSwgYXJyb3c9YXJyb3coZW5kcyA9ICJib3RoIiwgYW5nbGU9OTAsIGxlbmd0aCA9IHVuaXQoMSwgIm1tIikpLCBhbHBoYT0wLjUpICsKICBnZW9tX3BvaW50KGFlcyh4PS1hZ2VfcnVuaWYpLCBjb2w9InJlZCIsIGNleD0wLjUsIGFscGhhPTAuNSkgKwogIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIlRpbWUgKE15KSIpICsKICBzY2FsZV95X2Rpc2NyZXRlKG5hbWUgPSAiU3BlY2llcyIpICsKICBsYWJzKGNvbG91cj0iT2NjdXJyZW5jZVxuZGVuc2l0eSIpICsKICB0aGVtZShheGlzLnRleHQueT1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy55PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCkpICsKICBzY2FsZV9jb2xvcl9ncmFkaWVudG4oY29sb3VycyA9IGMoImRhcmtibHVlIiwgImZvcmVzdGdyZWVuIiwgImJsYWNrIiksIHRyYW5zPSJsb2ciLCBicmVha3M9YnJlYWtzLCBsYWJlbHM9YnJlYWtzKSArIAogIGdndGl0bGUocGFzdGUoIkRpc3RyaWJ1dGlvbnMgb2Ygc3BlY2llcyBmb3NzaWwgYWdlIHJhbmdlcywgYWZ0ZXIgY29ycmVjdGluZyBzYW1wbGluZyAobiA9ICIsIGRpbShDZXRhY2VhX29jY19zYW1wbGVkKVsxXSwgIikiLCBzZXA9IiIpKQpgYGAKCiRcdG8kIFNvbWUgaGlnaGx5IGRlbnNlIGNsdXN0ZXIgYmVjYW1lIG11Y2ggbW9yZSBzaW1pbGFyIHRvIHRoZSBvdGhlcnMuCgpgYGB7ciBmaWcuaGVpZ2h0PTV9CmNvbmRpdGlvbnMgPC0gQ2V0YWNlYV9vY2MkYWNjZXB0ZWRfcmFuayA9PSJzcGVjaWVzIiAmIENldGFjZWFfb2NjJGFnZV9yYW5nZTwxMAoKZ2dwbG90KENldGFjZWFfb2NjW2NvbmRpdGlvbnMsXSwgYWVzKHg9LWFnZV9ydW5pZikpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuNSwgYWxwaGE9MC41LCBmaWxsPSJyZWQiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKG5hbWUgPSAiVGltZSAoTXkpIikgKwogIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gIk51bWJlciBvZiBvY2N1cnJlbmNlcyIpICsKICBzY2FsZV9maWxsX2Rpc2NyZXRlKG5hbWU9IkFjY2VwdGVkIHJhbmsiKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpKSArCiAgZ2d0aXRsZShwYXN0ZSgiRXZvbHV0aW9uIG9mIHRoZSBzcGVjaWVzIG9jY3VycmVuY2UgbnVtYmVyIHRocm91Z2ggdGltZSAobiA9ICIsIGRpbShDZXRhY2VhX29jY1tjb25kaXRpb25zLF0pWzFdLCAiKSIsIHNlcD0iIikpCgpnZ3Bsb3QoQ2V0YWNlYV9vY2Nfc2FtcGxlZCwgYWVzKHg9LWFnZV9ydW5pZikpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuNSwgYWxwaGE9MC41LCBmaWxsPSJibHVlIikgKwogIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIlRpbWUgKE15KSIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobmFtZSA9ICJOdW1iZXIgb2Ygb2NjdXJyZW5jZXMiKSArCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lPSJBY2NlcHRlZCByYW5rIikgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIGdndGl0bGUocGFzdGUoIkV2b2x1dGlvbiBvZiB0aGUgc3BlY2llcyBvY2N1cnJlbmNlIG51bWJlciB0aHJvdWdoIHRpbWUsIGFmdGVyIGNvcnJlY3Rpb24gc2FtcGxpbmcgKG4gPSAiLCBkaW0oQ2V0YWNlYV9vY2Nfc2FtcGxlZClbMV0sICIpIiwgc2VwPSIiKSkKYGBgCgpJZiB3ZSBzdXBlcnBvc2UgdGhlc2UgMiBwbG90cyA6CgpgYGB7ciBmaWcuaGVpZ2h0PTV9CmNvbmRpdGlvbnMgPC0gQ2V0YWNlYV9vY2MkYWNjZXB0ZWRfcmFuayA9PSJzcGVjaWVzIiAmIENldGFjZWFfb2NjJGFnZV9yYW5nZTwxMAoKcDEgPC0gZ2dwbG90KENldGFjZWFfb2NjW2NvbmRpdGlvbnMsXSwgYWVzKHg9LWFnZV9ydW5pZikpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuNSwgYWxwaGE9MC41LCBmaWxsPSJyZWQiKSArCiAgdGhlbWVfdm9pZCgpCgpwMiA8LSBnZ3Bsb3QoQ2V0YWNlYV9vY2Nfc2FtcGxlZCwgYWVzKHg9LWFnZV9ydW5pZikpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuNSwgYWxwaGE9MC41LCBmaWxsPSJibHVlIikgKwogIHRoZW1lX3ZvaWQoKQoKcDEgKyBhbm5vdGF0aW9uX2N1c3RvbShnZ3Bsb3RHcm9iKHAyKSkKYGBgCgokXHRvJCBXZSBnZXQgdGhlIG5ldyBzcGVjaWVzIG9jY3VycmVuY2UgcmVwYXJ0aXRpb24gYWZ0ZXIgc3Vic2FtcGxpbmcgY29ycmVjdGlvbiwgdGhhdCBjb3VsZCBiZSB1c2VkIGZvciBkb2luZyBpbmZlcmVuY2Ugd2l0aCB0aGUgb2NjdXJyZW5jZSBiaXJ0aC1kZWF0aCBtb2RlbC4KCiMgTmV3IGRldmVsb3BtZW50cwoKIyMgQ29tcGFyZSB3aXRoIGEgUG9pc3NvbiBzYW1wbGluZyBwcm9jZXNzCgpJbiBvcmRlciB0byBjaGVjayBpZiB0aGUgZGF0YSBmaXQgb3VyIGFzc3VtcHRpb25zIG9mIGNvbnN0YW50LWZvc3NpbGlzYXRpb24tcmF0ZSBQb2lzc29uIHNhbXBsaW5nIHdlIGNvbXBhcmUgdGhlIG9ic2VydmVkIG9jY3VycmVuY2VzIGRpc3RyaWJ1dGlvbnMgd2l0aCB0aGUgZXhwZWN0ZWQgb25lcy4gU3BlY2lmaWNhbGx5LCB3ZSB3aWxsIGxvb2sgYXQgdGhlIG51bWJlciBvZiB0YXhhIHJlcHJlc2VudGVkIGJ5IDEsIDIsIDMsIC4uLiBvY2N1cnJlbmNlcyBhbmQgdGhlIG9uZSB0aGF0IHdlIHdvdWxkIGV4cGVjdCBmb3IgYSBnaXZlbiBkaXN0cmlidXRpb24gb2YgY29tYmluZWQgYWdlIHJhbmdlcyAoYXMgYSBwcm94eSBmb3Igc3BlY2llcyBkdXJhdGlvbikuCgpgYGB7ciBmaWcuaGVpZ2h0PTZ9CmNvbmRpdGlvbnMgPC0gIShDZXRhY2VhX29jYyRhY2NlcHRlZF9yYW5rICVpbiUgYygic3Vic3BlY2llcyIsICJpbmZyYW9yZGVyIikpICYgQ2V0YWNlYV9vY2MkYWdlX3JhbmdlPDEwCgpnZ3Bsb3QoQ2V0YWNlYV9vY2NbY29uZGl0aW9ucyxdLCBhZXMoeD1hZ2VfY29tYmluZWRfcmFuZ2UsIGZpbGw9YWNjZXB0ZWRfcmFuaykpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEpICsgCiAgI2dlb21fcG9pbnQoKSArCiAgc2NhbGVfeF9jb250aW51b3VzKG5hbWUgPSAiQWdlIHJhbmdlIChNeSkiKSArCiAgI3NjYWxlX3lfY29udGludW91cyh0cmFucyA9ICJsb2cxMCIsIG5hbWUgPSAiQ291bnQgKGxvZy1zY2FsZSkiKSArCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lPSJBY2NlcHRlZCByYW5rIikgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBsZWdlbmQucG9zaXRpb249ImJvdHRvbSIpICsKICBnZ3RpdGxlKCJPYnNlcnZlZCBkaXN0cmlidXRpb25zIG9mIGNvbWJpbmVkIGFnZSByYW5nZXMiKSArCiAgZmFjZXRfZ3JpZCguIH4gYWNjZXB0ZWRfcmFuaywgc2NhbGVzID0gImZyZWUiKQoKZ2dwbG90KENldGFjZWFfb2NjW2NvbmRpdGlvbnMsXSwgYWVzKHg9YWNjZXB0ZWRfbmFtZV9jb3VudCwgeT0odGFibGUoYWNjZXB0ZWRfbmFtZV9jb3VudCkvYXMubnVtZXJpYyhuYW1lcyh0YWJsZShhY2NlcHRlZF9uYW1lX2NvdW50KSkpKVthcy5mYWN0b3IoYWNjZXB0ZWRfbmFtZV9jb3VudCldLCBjb2w9YWNjZXB0ZWRfcmFuaykpICsKICBnZW9tX3BvaW50KCkgKwogIHNjYWxlX3hfY29udGludW91cyh0cmFucyA9ICJsb2cxMCIsIG5hbWUgPSAiTnVtYmVyIG9mIG9jY3VycmVuY2VzIGJ5IGFjY2VwdGVkIG5hbWUgKGxvZy1zY2FsZSkiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKHRyYW5zID0gImxvZzEwIiwgbmFtZSA9ICJOdW1iZXIgb2YgY29ycmVzcG9uZGluZyBhY2NlcHRlZCBuYW1lcyAobG9nLXNjYWxlKSIpICsKICBzY2FsZV9maWxsX2Rpc2NyZXRlKG5hbWU9IkFjY2VwdGVkIHJhbmsiKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCkpICsKICBnZ3RpdGxlKCJPYnNlcnZlZCBkaXN0cmlidXRpb25zIG9mIHRoZSBudW1iZXIgb2YgYWNjZXB0ZWQgbmFtZXMgd2l0aCB0aGUgc2FtZSBudW1iZXIgb2Ygb2NjdXJyZW5jZXMiKSArCiAgZmFjZXRfZ3JpZChhY2NlcHRlZF9yYW5rIH4gLiwgc2NhbGVzID0gImZyZWUiKQpgYGAKCkluIGEgUG9pc3NvbiBwcm9jZXNzIHdpdGggb2NjdXJyZW5jZSBzYW1wbGluZyByYXRlICRcb21lZ2EkIGFuZCBmb3IgYSBnaXZlbiB0aW1lIGludGVydmFsIG9mIGxlbmd0aCAkdCQsIHRoZSBwcm9iYWJpbGl0eSBvZiBvYnNlcnZpbmcgJE5fdCA9IGskIG9jY3VycmVuY2VzIGlzIGdpdmVuIGJ5IHRoZSBQb2lzc29uIGRpc3RyaWJ1dGlvbiBvZiBtZWFuIG9mIHBhcmFtZXRlciAkXG9tZWdhXHRpbWVzIHQkIDogCgokJFxtYXRoYmJ7UH0oTl90PWspID0gZV57LVxvbWVnYSB0fVxmcmFjeyhcb21lZ2EgdClea317ayF9JCQKClNvIGluIG9yZGVyIHRvIGhhdmUgdGhlIGFic29sdXRlIHByb2JhYmlsaXR5IG9mIG9ic2VydmluZyAkTl8wID0gbiQgb2NjdXJyZW5jZXMgd2UgaGF2ZSB0byBpbnRlZ3JhdGUgb3ZlciB0aGUgZnVsbCBkaXN0cmlidXRpb24gb2YgYWdlIHJhbmdlcyAkdCQsIGNhbGxlZCAkZih0KSQgOgoKJCRcbWF0aGJie1B9KE5fMCA9IG4pID0gXGludF90IFAoTl90ID0gbikgZih0KSBkdCA9IFxpbnRfdCBlXnstXG9tZWdhIHR9XGZyYWN7KFxvbWVnYSB0KV5ufXtuIX0gZih0KSBkdCQkCgpGaXJzdCwgIGFwcHJveGltYXRlIHRoaXMgZGlzdHJpYnV0aW9uIDoKCmBgYHtyfQpyYW5nZV9kZW5zaXR5IDwtIGFwcHJveGZ1bihkZW5zaXR5KENldGFjZWFfb2NjW0NldGFjZWFfb2NjJGFjY2VwdGVkX3Jhbms9PSJzcGVjaWVzIixdJGFnZV9jb21iaW5lZF9yYW5nZVtpcy5maW5pdGUoQ2V0YWNlYV9vY2NbQ2V0YWNlYV9vY2MkYWNjZXB0ZWRfcmFuaz09InNwZWNpZXMiLF0kYWdlX2NvbWJpbmVkX3JhbmdlKV0pKQoKaGlzdChDZXRhY2VhX29jY1tDZXRhY2VhX29jYyRhY2NlcHRlZF9yYW5rPT0ic3BlY2llcyIsXSRhZ2VfY29tYmluZWRfcmFuZ2UsIHByb2JhYmlsaXR5ID0gVCwgYnJlYWtzID0gMjAsIG1haW49IkRlbnNpdHkgYXBwcm94aW1hdGlvbiBvZiB0aGUgZW1waXJpY2FsIHJhbmdlIGRpc3RyaWJ1dGlvbiIsIHhsYWIgPSAiQWdlIHJhbmdlIChNeSkiKQpsaW5lcygxOjEwMC81LCByYW5nZV9kZW5zaXR5KDE6MTAwLzUpKQpgYGAKClRoZW4gaW50ZWdyYXRlIGFuZCBwbG90IHRoZSBleHBlY3RlZCBkaXN0cmlidXRpb24gZm9yIGEgZ2l2ZW4gb21lZ2EgOgoKYGBge3J9CmV4cGVjdGVkX2Rpc3RyaWJ1dGlvbiA8LSBmdW5jdGlvbihuLCBvbWVnYSwgYWdlX2NvbWJpbmVkX3JhbmdlKXsKICByYW5nZV9kZW5zaXR5IDwtIGFwcHJveGZ1bihkZW5zaXR5KGFnZV9jb21iaW5lZF9yYW5nZVtpcy5maW5pdGUoYWdlX2NvbWJpbmVkX3JhbmdlKV0pKQogIGcgPC0gZnVuY3Rpb24odCl7ZHBvaXMobiwgb21lZ2EqdCkqcmFuZ2VfZGVuc2l0eSh0KX0KICByZXR1cm4gKGludGVncmF0ZShnLCBsb3dlciA9IDEsIHVwcGVyID0gbWF4KGFnZV9jb21iaW5lZF9yYW5nZSkpKQp9CgpvbWVnYSA8LSAwLjEKCmRlbnMgPC0gc2FwcGx5KDA6MjAsIGZ1bmN0aW9uKG4pe2V4cGVjdGVkX2Rpc3RyaWJ1dGlvbihuLCBvbWVnYSwgQ2V0YWNlYV9vY2NbQ2V0YWNlYV9vY2MkYWNjZXB0ZWRfcmFuaz09InNwZWNpZXMiLF0kYWdlX2NvbWJpbmVkX3JhbmdlKSR2YWx1ZX0pCgpwbG90KDA6MjAsIGRlbnMsIG1haW49IkV4cGVjdGVkIGRpc3RyaWJ1dGlvbiBvZiB0aGUgbnVtYmVyIG9mIGFjY2VwdGVkIG5hbWVzIHdpdGggdGhlIHNhbWUgbnVtYmVyIG9mIG9jY3VycmVuY2VzIiwgeGxhYj0iTnVtYmVyIG9mIG9jY3VycmVuY2VzIHdpdGggdGhlIHNhbWUgYWNjZXB0ZWQgbmFtZSIsIHlsYWIgPSAiUHJvcG9ydGlvbnMiLCB0eXBlID0gImIiKQpgYGAKCkZpbmFsbHksIHRyeSB0byBmaW5kIGFuICRcb21lZ2EkIHZhbHVlIHRoYXQgYXBwcm94aW1hdGVseSBmaXRzIHRoZSBmaXJzdCBwb2ludHMgKHRoZSBsZWFzdCBhZmZlY3RlZCBieSBvdmVyc2FtcGxpbmcgYmlhc2VzKSBhbmQgY2hlY2sgaWYgdGhlIG90aGVyIHBvaW50cyBmb2xsb3cgdGhlIGV4cGVjdGVkIGN1cnZlIDoKCmBgYHtyIGZpZy5oZWlnaHQ9Nn0KIyBSZWNvdW50IHRoZSBudW1iZXIgb2Ygb2NjdXJyZW5jZXMgd2l0aCB0aGUgc2FtZSBhY2NlcHRlZCBuYW1lIGFmdGVyIHRoZSBzYW1wbGluZwpDZXRhY2VhX29jY19zYW1wbGVkJGFjY2VwdGVkX25hbWVfY291bnQgPC0gc2FwcGx5KENldGFjZWFfb2NjX3NhbXBsZWQkYWNjZXB0ZWRfbmFtZSwgZnVuY3Rpb24oeCl7dGFibGUoQ2V0YWNlYV9vY2Nfc2FtcGxlZCRhY2NlcHRlZF9uYW1lKVt4XX0pCgpvbWVnYSA8LSAwLjEKYWNjZXB0ZWRfbmFtZV9jb3VudF9zcGVjaWVzIDwtIENldGFjZWFfb2NjW0NldGFjZWFfb2NjJGFjY2VwdGVkX3Jhbms9PSJzcGVjaWVzIixdJGFjY2VwdGVkX25hbWVfY291bnQKZGVucyA8LSBzYXBwbHkoMTptYXgoYWNjZXB0ZWRfbmFtZV9jb3VudF9zcGVjaWVzKSwgZnVuY3Rpb24obil7IGV4cGVjdGVkX2Rpc3RyaWJ1dGlvbihuLCBvbWVnYSwgQ2V0YWNlYV9vY2NbQ2V0YWNlYV9vY2MkYWNjZXB0ZWRfcmFuaz09InNwZWNpZXMiLF0kYWdlX2NvbWJpbmVkX3JhbmdlKSR2YWx1ZSB9KQphY2NlcHRlZF9uYW1lX2NvdW50X2NhdGVnb3JpZXMgPC0gdGFibGUoYWNjZXB0ZWRfbmFtZV9jb3VudF9zcGVjaWVzKS9hcy5udW1lcmljKG5hbWVzKHRhYmxlKGFjY2VwdGVkX25hbWVfY291bnRfc3BlY2llcykpKSAgIyBOdW1iZXIgb2YgY2F0ZWdvcmllcyB3aXRoIDEsIDIsIDMsIC4uLiBvY2N1cnJlbmNlcyBvZiB0aGUgc2FtZSBzcGVjaWVzCgojIENvbXBhcmUgdGhlIGluaXRpYWwgb2JzZXJ2ZWQgZGlzdHJpYnV0aW9uIHdpdGggdGhlIHRoZW9yZXRpY2FsIGN1cnZlCmdncGxvdChDZXRhY2VhX29jY1tDZXRhY2VhX29jYyRhY2NlcHRlZF9yYW5rPT0ic3BlY2llcyIsXSwKICAgICAgIGFlcyh4PWFjY2VwdGVkX25hbWVfY291bnQsIAogICAgICAgICAgIHk9YWNjZXB0ZWRfbmFtZV9jb3VudF9jYXRlZ29yaWVzW2FzLmZhY3RvcihhY2NlcHRlZF9uYW1lX2NvdW50KV0sIAogICAgICAgICAgIGZpbGw9YWNjZXB0ZWRfcmFuaykpICsKICBnZW9tX3BvaW50KCkgKwogIAogIGFubm90YXRlKCJsaW5lIiwgeCA9IDE6bWF4KGFjY2VwdGVkX25hbWVfY291bnRfc3BlY2llcyksIHk9IGRlbnMKICAgICptYXgoYWNjZXB0ZWRfbmFtZV9jb3VudF9jYXRlZ29yaWVzW2FzLmZhY3RvcihhY2NlcHRlZF9uYW1lX2NvdW50X3NwZWNpZXMpXSkgL21heChkZW5zKSkrCiAgCiAgc2NhbGVfeF9jb250aW51b3VzKG5hbWUgPSAiTnVtYmVyIG9mIG9jY3VycmVuY2VzIGJ5IGFjY2VwdGVkIG5hbWUiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKHRyYW5zID0gImxvZzEwIiwgbmFtZSA9ICJOdW1iZXIgb2YgY29ycmVzcG9uZGluZyBhY2NlcHRlZCBuYW1lcyAobG9nLXNjYWxlKSIpICsKICBzY2FsZV9maWxsX2Rpc2NyZXRlKG5hbWU9Ik9ic2VydmVkIGRpc3RyaWJ1dGlvbiIpICsKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIGdndGl0bGUoIkNvbXBhcmlzb24gYmV0d2VlbiBleHBlY3RlZCBhbmQgb2JzZXJ2ZWQgZGlzdHJpYnV0aW9ucyBvZiBudW1iZXIgb2Ygb2NjdXJyZW5jZXMiKSArCiAgZmFjZXRfZ3JpZChhY2NlcHRlZF9yYW5rIH4gLiwgc2NhbGVzID0gImZyZWUiKQoKYWNjZXB0ZWRfbmFtZV9jb3VudF9zcGVjaWVzX3NhbXBsZWQgPC0gQ2V0YWNlYV9vY2Nfc2FtcGxlZFtDZXRhY2VhX29jY19zYW1wbGVkJGFjY2VwdGVkX3Jhbms9PSJzcGVjaWVzIixdJGFjY2VwdGVkX25hbWVfY291bnQKZGVuc19zYW1wbGVkIDwtIHNhcHBseSgxOm1heChhY2NlcHRlZF9uYW1lX2NvdW50X3NwZWNpZXNfc2FtcGxlZCksIGZ1bmN0aW9uKG4pewogICAgIGV4cGVjdGVkX2Rpc3RyaWJ1dGlvbihuLCBvbWVnYSwgQ2V0YWNlYV9vY2Nfc2FtcGxlZFtDZXRhY2VhX29jY19zYW1wbGVkJGFjY2VwdGVkX3Jhbms9PSJzcGVjaWVzIixdJGFnZV9jb21iaW5lZF9yYW5nZSkkdmFsdWUKICAgIH0pCmFjY2VwdGVkX25hbWVfY291bnRfY2F0ZWdvcmllc19zYW1wbGVkIDwtIHRhYmxlKGFjY2VwdGVkX25hbWVfY291bnRfc3BlY2llc19zYW1wbGVkKS9hcy5udW1lcmljKG5hbWVzKHRhYmxlKGFjY2VwdGVkX25hbWVfY291bnRfc3BlY2llc19zYW1wbGVkKSkpICAjIE51bWJlciBvZiBjYXRlZ29yaWVzIHdpdGggMSwgMiwgMywgLi4uIG9jY3VycmVuY2VzIG9mIHRoZSBzYW1lIHNwZWNpZXMKCiMgQ29tcGFyZSB0aGUgY29ycmVjdGVkIG9ic2VydmVkIGRpc3RyaWJ1dGlvbiB3aXRoIHRoZSB0aGVvcmV0aWNhbCBjdXJ2ZQpnZ3Bsb3QoQ2V0YWNlYV9vY2Nfc2FtcGxlZFtDZXRhY2VhX29jY19zYW1wbGVkJGFjY2VwdGVkX3Jhbms9PSJzcGVjaWVzIixdLCAKICAgICAgIGFlcyh4PWFjY2VwdGVkX25hbWVfY291bnQsCiAgICAgICAgICAgeT1hY2NlcHRlZF9uYW1lX2NvdW50X2NhdGVnb3JpZXNfc2FtcGxlZFthcy5mYWN0b3IoYWNjZXB0ZWRfbmFtZV9jb3VudCldLAogICAgICAgICAgIGZpbGw9YWNjZXB0ZWRfcmFuaykpICsKICBnZW9tX3BvaW50KCkgKwogIAogIGFubm90YXRlKCJsaW5lIiwgeCA9IDE6bWF4KGFjY2VwdGVkX25hbWVfY291bnRfc3BlY2llc19zYW1wbGVkKSwgeT0gZGVuc19zYW1wbGVkCiAgICAqbWF4KGFjY2VwdGVkX25hbWVfY291bnRfY2F0ZWdvcmllc19zYW1wbGVkW2FzLmZhY3RvcihhY2NlcHRlZF9uYW1lX2NvdW50X3NwZWNpZXNfc2FtcGxlZCldKSAvbWF4KGRlbnNfc2FtcGxlZCkpICsKICAKICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJOdW1iZXIgb2Ygb2NjdXJyZW5jZXMgYnkgYWNjZXB0ZWQgbmFtZSIpICsKICBzY2FsZV95X2NvbnRpbnVvdXModHJhbnMgPSAibG9nMTAiLCBuYW1lID0gIk51bWJlciBvZiBjb3JyZXNwb25kaW5nIGFjY2VwdGVkIG5hbWVzIChsb2ctc2NhbGUpIikgKwogIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZT0iT2JzZXJ2ZWQgZGlzdHJpYnV0aW9uIikgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpKSArCiAgZ2d0aXRsZSgiQ29tcGFyaXNvbiBiZXR3ZWVuIGV4cGVjdGVkIGFuZCBvYnNlcnZlZCBkaXN0cmlidXRpb25zIG9mIG51bWJlciBvZiBvY2N1cnJlbmNlcywgYWZ0ZXIgc2FtcGxpbmciKSArCiAgZmFjZXRfZ3JpZChhY2NlcHRlZF9yYW5rIH4gLiwgc2NhbGVzID0gImZyZWUiKQpgYGAKCiRcaW1wbGllcyQgSW5pdGlhbCBvYnNlcnZhdGlvbnMgcmVhbGx5IGRvIG5vdCBmaXQgdGhlIGV4cGVjdGF0aW9ucywgKipzcGVjaWVzIHdpdGggbW9yZSB0aGFuIDUgb2NjdXJyZW5jZXMgbXVzdCByZW1haW4gdmVyeSByYXJlKiogISBCdXQgb3VyIHN1YnNhbXBsaW5nIHNlZW1zIHRvIGNvcnJlY3QgbW9zdCBvZiB0aGlzIGJpYXMuCgpIb3dldmVyLCB0aGlzIG1ldGhvZCByZXF1aXJlcyB0byBtYWtlIHNldmVyYWwgYXJiaXRyYXJ5IGNob2ljZXMgdGhhdCBtYXkgaW50cm9kdWNlIG5ldyBiaWFzZXMgc28gd2Ugd2lsbCBpbnN0ZWFkIHN1YnNhbXBsZSBhdCBvdGhlciBsZXZlbHMgKHBhbGFlb250b2xvZ2ljYWwgY29sbGVjdGlvbiwgZ2VvbG9naWNhbCBmb3JtYXRpb24pLiBJbiBlYWNoIGNhc2Ugb25seSBvbmUgb2NjdXJyZW5jZSB3aWxsIGJlIHNhbXBsZWQgZm9yIHRoZSBzaW1pbGFybHkgaWRlbnRpZmllZCwgYSBwcm9jZXNzIHdlIHdpbGwgcmVmZXIgdG8gYXMgKiphZ2dyZWdhdGluZyoqIHRoZXNlIG9jY3VycmVuY2VzIGFjY29yZGluZyB0byB0aGUgY2hvc2VuIGZhY3Rvci4KCiMjIEFnZ3JlZ2F0ZSBzaW1pbGFybHkgaWRlbnRpZmllZCBvY2N1cnJlbmNlcyBpbiBlYWNoIGNvbGxlY3Rpb24KCmBgYHtyIGZpZy5oZWlnaHQ9Nn0KZm9yIChuIGluIDU6MTApewogIEEgPC0gQ2V0YWNlYV9vY2NbYXMubG9naWNhbCh0YWJsZShDZXRhY2VhX29jYyRjb2xsZWN0aW9uX25vKVtDZXRhY2VhX29jYyRjb2xsZWN0aW9uX25vXT09biksXQogIEEkY29sbGVjdGlvbl9ubyA8LSBkcm9wbGV2ZWxzKEEkY29sbGVjdGlvbl9ubykKCiAgcCA8LSBnZ3Bsb3QoQSwgYWVzKHg9LWFnZV9tZWFuLCBmaWxsPWFjY2VwdGVkX25hbWUpKSArCiAgICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuNSwgY29sPSJibGFjayIpICsKICAgIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIlRpbWUgKE15KSIpICsKICAgIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gIk51bWJlciBvZiBvY2N1cnJlbmNlcyBpbiB0aGUgY29sbGVjdGlvbiIpICsKICAgIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICAgZ2d0aXRsZShwYXN0ZSgiRGlzdHJpYnV0aW9uIG9mIG9jY3VycmVuY2VzJyBtZWFuIGFnZSBmb3IgY29sbGVjdGlvbnMgd2l0aCIsIG4sICJvY2N1cnJlbmNlcyAoY29sb3JlZCBieSB0YXhhKSIpKSArCiAgICBmYWNldF9ncmlkKGNvbGxlY3Rpb25fbm8gfiAuLCBzY2FsZXM9ImZyZWUiKQogIHByaW50KHApCn0KCkEgPC0gQ2V0YWNlYV9vY2NbYXMubG9naWNhbCh0YWJsZShDZXRhY2VhX29jYyRjb2xsZWN0aW9uX25vKVtDZXRhY2VhX29jYyRjb2xsZWN0aW9uX25vXT4xMCksXQpBJGNvbGxlY3Rpb25fbm8gPC0gZHJvcGxldmVscyhBJGNvbGxlY3Rpb25fbm8pCgpnZ3Bsb3QoQSwgYWVzKHg9LWFnZV9tZWFuLCBmaWxsPWFjY2VwdGVkX25hbWUpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjUsIGNvbD0iYmxhY2siKSArCiAgc2NhbGVfeF9jb250aW51b3VzKG5hbWUgPSAiVGltZSAoTXkpIikgKwogIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gIk51bWJlciBvZiBvY2N1cnJlbmNlcyBpbiB0aGUgY29sbGVjdGlvbiIpICsKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgZ2d0aXRsZSgiRGlzdHJpYnV0aW9uIG9mIG9jY3VycmVuY2VzJyBtZWFuIGFnZSBmb3IgY29sbGVjdGlvbnMgd2l0aCA+MTAgb2NjdXJyZW5jZXMiKSArCiAgZmFjZXRfZ3JpZChjb2xsZWN0aW9uX25vIH4gLiwgc2NhbGVzPSJmcmVlIikKYGBgCgokXHRvJCBFYWNoIGNvbGxlY3Rpb24gY29ycmVzcG9uZHMgdG8gYSB1bmlxdWUgdGltZSBpbnRlcnZhbCAoaW5mZXJyZWQgZnJvbSB0aGUgdW5pcXVlIGFnZSBtZWFuKS4KCkluIG9yZGVyIHRvIHJlZHVjZSB0aGUgYWJ1bmRhbmNlIGJpYXMsIHdlIG1heSBrZWVwIG9ubHkgb25lIG9jY3VycmVuY2UgZm9yIGVhY2ggY29sbGVjdGlvbiA6CgpgYGB7cn0KQ2V0YWNlYV9vY2NfYWdncmVnIDwtIGMoKQoKIyBCcm93c2UgYWxsIGNvbGxlY3Rpb25zCmNvbGxlY3Rpb25zIDwtIGxldmVscyhkcm9wbGV2ZWxzKENldGFjZWFfb2NjJGNvbGxlY3Rpb25fbm8pKQpmb3IgKGNvbGwgaW4gY29sbGVjdGlvbnMpewogIENldGFjZWFfb2NjX2NvbGwgPC0gQ2V0YWNlYV9vY2NbQ2V0YWNlYV9vY2MkY29sbGVjdGlvbl9ubz09Y29sbCxdCiAgCiAgIyBCcm93c2UgYWxsIGFjY2VwdGVkIG5hbWVzIGluIGVhY2ggY29sbGVjdGlvbiAmIHNhbXBsZSBvbmx5IDEgb2NjdXJyZW5jZQogIHRheGEgPC0gbGV2ZWxzKGRyb3BsZXZlbHMoQ2V0YWNlYV9vY2NfY29sbCRhY2NlcHRlZF9uYW1lKSkKICBmb3IgKG5hbWUgaW4gdGF4YSl7CiAgICBDZXRhY2VhX29jY19hZ2dyZWcgPC0gcmJpbmQoQ2V0YWNlYV9vY2NfYWdncmVnLCBzYW1wbGVfbihDZXRhY2VhX29jY19jb2xsW0NldGFjZWFfb2NjX2NvbGwkYWNjZXB0ZWRfbmFtZT09bmFtZSxdLCBzaXplID0gMSkpCiAgfQp9CgpkYXRhLmZyYW1lKENldGFjZWFfb2NjID0gYyhkaW0oQ2V0YWNlYV9vY2MpWzFdLAogICAgICAgICAgICAgICAgICAgICAgICAgICBkaW0oQ2V0YWNlYV9vY2NbQ2V0YWNlYV9vY2MkYWNjZXB0ZWRfcmFuayA9PSJzcGVjaWVzIixdKVsxXSksCiAgICAgICAgICAgQ2V0YWNlYV9vY2NfYWdncmVnID0gYyhkaW0oQ2V0YWNlYV9vY2NfYWdncmVnKVsxXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbShDZXRhY2VhX29jY19hZ2dyZWdbQ2V0YWNlYV9vY2NfYWdncmVnJGFjY2VwdGVkX3JhbmsgPT0ic3BlY2llcyIsXSlbMV0pLAogICAgICAgICAgIHJlbW92ZWQgPSBjKGRpbShDZXRhY2VhX29jYylbMV0tZGltKENldGFjZWFfb2NjX2FnZ3JlZylbMV0sCiAgICAgICAgICAgICAgICAgICAgICAgZGltKENldGFjZWFfb2NjW0NldGFjZWFfb2NjJGFjY2VwdGVkX3JhbmsgPT0ic3BlY2llcyIsXSlbMV0tZGltKENldGFjZWFfb2NjX2FnZ3JlZ1tDZXRhY2VhX29jY19hZ2dyZWckYWNjZXB0ZWRfcmFuayA9PSJzcGVjaWVzIixdKVsxXSksCiAgICAgICAgICAgcm93Lm5hbWVzID0gYygiTnVtYmVyIG9mIG9jY3VycmVuY2VzIiwgIk51bWJlciBvZiBvY2N1cnJlbmNlcyAoc3BlY2llcyBvbmx5KSIpKQpgYGAKCiRcdG8kIE5vdCBlbm91Z2ggb2NjdXJyZW5jZXMgYXJlIHJlbW92ZWQgdG8gbWFrZSBhIHN1ZmZpY2llbnQgZGlmZmVyZW5jZS4gSWYgd2UgbG9vayBhdCB0aGUgY29sbGVjdGlvbiB3aXRoIHRoZSBoaWdoZXN0IG51bWJlciBvZiBvY2N1cnJlbmNlcyA6CgpgYGB7cn0KY29sbGVjdGlvbl9tYXhfb2NjdXJyZW5jZXMgPC0gbWF4KHRhYmxlKENldGFjZWFfb2NjJGNvbGxlY3Rpb25fbm8pW0NldGFjZWFfb2NjJGNvbGxlY3Rpb25fbm9dKQpjb2xsZWN0aW9uX21heF9ubyA8LSBuYW1lcyh0YWJsZShDZXRhY2VhX29jYyRjb2xsZWN0aW9uX25vKVtDZXRhY2VhX29jYyRjb2xsZWN0aW9uX25vXVt0YWJsZShDZXRhY2VhX29jYyRjb2xsZWN0aW9uX25vKVtDZXRhY2VhX29jYyRjb2xsZWN0aW9uX25vXT09Y29sbGVjdGlvbl9tYXhfb2NjdXJyZW5jZXNdWzFdKQoKdGFibGUoZHJvcGxldmVscyhDZXRhY2VhX29jY1tDZXRhY2VhX29jYyRjb2xsZWN0aW9uX25vPT1jb2xsZWN0aW9uX21heF9ubyxdJGFjY2VwdGVkX25hbWUpKQpgYGAKCiRcdG8kIFRoZXJlIGFyZSB2ZXJ5IGZldyByZWR1bmRhbmNpZXMgYW1vbmcgdGhlIGFjY2VwdGVkIG5hbWVzIGluIGNvbGxlY3Rpb25zIHNvIGFnZ3JlZ2F0aW5nIHRob3NlIHdvbid0IHJlZHVjZSB0aGUgYWJ1bmRhbmNlIGJpYXMuCgpJbnN0ZWFkLCB3ZSBtYXkgdHJ5IHRvICoqYWdncmVnYXRlIG9jY3VycmVuY2VzIHdpdGggdGhlIHNhbWUgYWNjZXB0ZWQgbmFtZSBhdCB0aGUgbGV2ZWwgb2YgdGhlIGdlb2xvZ2ljYWwgZm9ybWF0aW9uKiogKGllIHN1YnNhbXBsZSBvbmx5IG9uZSBmb3IgZWFjaCkuCgojIyBBZ2dyZWdhdGUgc2ltaWxhcmx5IGlkZW50aWZpZWQgb2NjdXJyZW5jZXMgaW4gZWFjaCBmb3JtYXRpb24KCmBgYHtyIGZpZy5oZWlnaHQ9OH0KQ2V0YWNlYV9vY2Nfc3BlY2llcyA8LSBDZXRhY2VhX29jY1tDZXRhY2VhX29jYyRhY2NlcHRlZF9yYW5rPT0ic3BlY2llcyIsXQoKIyBCcm93c2UgYWxsIG51bWJlcnMgb2Ygb2NjdXJyZW5jZXMgYnkgZm9ybWF0aW9uCmZvcm1hdGlvbl9vY2N1cnJlbmNlc19uYiA8LSBhcy5udW1lcmljKG5hbWVzKHRhYmxlKHRhYmxlKGRyb3BsZXZlbHMoQ2V0YWNlYV9vY2Nfc3BlY2llcyRmb3JtYXRpb24pKSkpKQoKZm9yIChuIGluIGxpc3QoYyg0LCA3KSwgYyg4LCAxNSksIGMoMTYsIDEyNCkpKXsKICBBIDwtIENldGFjZWFfb2NjX3NwZWNpZXNbYXMubG9naWNhbCh0YWJsZShDZXRhY2VhX29jY19zcGVjaWVzJGZvcm1hdGlvbilbQ2V0YWNlYV9vY2Nfc3BlY2llcyRmb3JtYXRpb25dPj1uWzFdKQogICAgICAgICAgICAgICAgICAgICAgICAgICAmIGFzLmxvZ2ljYWwodGFibGUoQ2V0YWNlYV9vY2Nfc3BlY2llcyRmb3JtYXRpb24pW0NldGFjZWFfb2NjX3NwZWNpZXMkZm9ybWF0aW9uXTw9blsyXSksXQogIEEkZm9ybWF0aW9uIDwtIGRyb3BsZXZlbHMoQSRmb3JtYXRpb24pCgogIHAgPC0gZ2dwbG90KEEsIGFlcyh4PS1hZ2VfbWVhbiwgZmlsbD1hY2NlcHRlZF9uYW1lKSkgKwogICAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjUsIGNvbD0iYmxhY2siKSArCiAgICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJUaW1lIChNeSkiKSArCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobmFtZSA9ICJOdW1iZXIgb2Ygb2NjdXJyZW5jZXMgaW4gdGhlIGZvcm1hdGlvbiIpICsKICAgIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZT0iQWNjZXB0ZWQgbmFtZSIpICsKICAgIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICAgZ2d0aXRsZShwYXN0ZSgiRGlzdHJpYnV0aW9uIG9mIG9jY3VycmVuY2VzJyBtZWFuIGFnZSBmb3IgZm9ybWF0aW9ucyB3aXRoIiwgblsxXSwgIi0iLCBuWzJdLCAib2NjdXJyZW5jZXMgKGNvbG9yZWQgYnkgc3BlY2llcykiKSkgKwogICAgZmFjZXRfZ3JpZChmb3JtYXRpb24gfiAuLCBzY2FsZXM9ImZyZWUiKQogIHByaW50KHApCn0KCm1heF9zcGVjaWVzX2J5X2Zvcm1hdGlvbiA8LSBtYXgodGFibGUoQ2V0YWNlYV9vY2Nfc3BlY2llcyRmb3JtYXRpb24pKQpBIDwtIENldGFjZWFfb2NjX3NwZWNpZXNbYXMubG9naWNhbCh0YWJsZShDZXRhY2VhX29jY19zcGVjaWVzJGZvcm1hdGlvbilbQ2V0YWNlYV9vY2Nfc3BlY2llcyRmb3JtYXRpb25dPT1tYXhfc3BlY2llc19ieV9mb3JtYXRpb24pLF0KQSRmb3JtYXRpb24gPC0gZHJvcGxldmVscyhBJGZvcm1hdGlvbikKCmdncGxvdChBLCBhZXMoeD0tYWdlX21lYW4sIGZpbGw9cmVvcmRlcihhY2NlcHRlZF9uYW1lLCAtYWdlX21lYW4pKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC41LCBjb2w9ImJsYWNrIikgKwogIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIlRpbWUgKE15KSIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobmFtZSA9ICJOdW1iZXIgb2Ygb2NjdXJyZW5jZXMgaW4gdGhlIGZvcm1hdGlvbiIpICsKICBzY2FsZV9maWxsX2Rpc2NyZXRlKG5hbWU9IkFjY2VwdGVkIG5hbWUiKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogIGdndGl0bGUocGFzdGUoIkRpc3RyaWJ1dGlvbiBvZiBvY2N1cnJlbmNlcycgbWVhbiBhZ2UgZm9yIiwgbWF4X3NwZWNpZXNfYnlfZm9ybWF0aW9uLCAib2NjdXJyZW5jZXMgd2l0aG91dCBpbmRpY2F0ZWQgZm9ybWF0aW9uIChjb2xvcmVkIGJ5IHNwZWNpZXMpIikpICsKICBmYWNldF9ncmlkKGZvcm1hdGlvbiB+IC4pCmBgYAoKJFx0byQgRm9yIG1vc3QgZm9ybWF0aW9ucyBlYWNoIHNwZWNpZXMgc2VlbXMgdG8gYmUgcmVzdHJpY3RlZCB0byBvbmx5IG9uZSBhZ2UsIHNvIGFzIGV4cGVjdGVkIHdlIGFyZSBub3QgbG9vc2luZyB0b28gbXVjaCBpbmZvcm1hdGlvbiB3aGVuIGFnZ3JlZ2F0aW5nIHRoZW0gdG8gYSBzaW5nbGUgb2NjdXJyZW5jZS4KCmBgYHtyfQpDZXRhY2VhX29jY19hZ2dyZWcgPC0gYygpCgojIEJyb3dzZSBhbGwgZm9ybWF0aW9ucwpmb3JtYXRpb25zIDwtIGxldmVscyhkcm9wbGV2ZWxzKENldGFjZWFfb2NjJGZvcm1hdGlvbikpCmZvciAoZm9ybSBpbiBmb3JtYXRpb25zKXsKICBDZXRhY2VhX29jY19mb3JtIDwtIENldGFjZWFfb2NjW0NldGFjZWFfb2NjJGZvcm1hdGlvbj09Zm9ybSxdCiAgCiAgIyBCcm93c2UgYWxsIGFjY2VwdGVkIG5hbWVzIGluIGVhY2ggZm9ybWF0aW9uICYgc2FtcGxlIG9ubHkgMSBvY2N1cnJlbmNlCiAgdGF4YSA8LSBsZXZlbHMoZHJvcGxldmVscyhDZXRhY2VhX29jY19mb3JtJGFjY2VwdGVkX25hbWUpKQogIGZvciAobmFtZSBpbiB0YXhhKXsKICAgIENldGFjZWFfb2NjX2FnZ3JlZyA8LSByYmluZChDZXRhY2VhX29jY19hZ2dyZWcsIHNhbXBsZV9uKENldGFjZWFfb2NjX2Zvcm1bQ2V0YWNlYV9vY2NfZm9ybSRhY2NlcHRlZF9uYW1lPT1uYW1lLF0sIHNpemUgPSAxKSkKICB9Cn0KCmRhdGEuZnJhbWUoQ2V0YWNlYV9vY2MgPSBjKGRpbShDZXRhY2VhX29jYylbMV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbShDZXRhY2VhX29jY1tDZXRhY2VhX29jYyRhY2NlcHRlZF9yYW5rID09InNwZWNpZXMiLF0pWzFdKSwKICAgICAgICAgICBDZXRhY2VhX29jY19hZ2dyZWcgPSBjKGRpbShDZXRhY2VhX29jY19hZ2dyZWcpWzFdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltKENldGFjZWFfb2NjX2FnZ3JlZ1tDZXRhY2VhX29jY19hZ2dyZWckYWNjZXB0ZWRfcmFuayA9PSJzcGVjaWVzIixdKVsxXSksCiAgICAgICAgICAgcmVtb3ZlZCA9IGMoZGltKENldGFjZWFfb2NjKVsxXS1kaW0oQ2V0YWNlYV9vY2NfYWdncmVnKVsxXSwKICAgICAgICAgICAgICAgICAgICAgICBkaW0oQ2V0YWNlYV9vY2NbQ2V0YWNlYV9vY2MkYWNjZXB0ZWRfcmFuayA9PSJzcGVjaWVzIixdKVsxXS1kaW0oQ2V0YWNlYV9vY2NfYWdncmVnW0NldGFjZWFfb2NjX2FnZ3JlZyRhY2NlcHRlZF9yYW5rID09InNwZWNpZXMiLF0pWzFdKSwKICAgICAgICAgICByb3cubmFtZXMgPSBjKCJOdW1iZXIgb2Ygb2NjdXJyZW5jZXMiLCAiTnVtYmVyIG9mIG9jY3VycmVuY2VzIChzcGVjaWVzIG9ubHkpIikpCmBgYAoKJFx0byQgSW4gdGhhdCBjYXNlIHRoZSBzdWItc2FtcGxpbmcgaXMgYmlnIGVub3VnaCB0byBob3BlIGNvcnJlY3Rpbmcgb3VyIGJpYXMuCgpgYGB7ciBmaWcuaGVpZ2h0PTd9CiMgUmVjb3VudCB0aGUgbnVtYmVyIG9mIG9jY3VycmVuY2VzIHdpdGggdGhlIHNhbWUgYWNjZXB0ZWQgbmFtZSBhZnRlciB0aGUgYWdncmVnYXRpb24KQ2V0YWNlYV9vY2NfYWdncmVnJGFjY2VwdGVkX25hbWVfY291bnQgPC0gc2FwcGx5KENldGFjZWFfb2NjX2FnZ3JlZyRhY2NlcHRlZF9uYW1lLCBmdW5jdGlvbih4KXt0YWJsZShDZXRhY2VhX29jY19hZ2dyZWckYWNjZXB0ZWRfbmFtZSlbeF19KQoKb21lZ2EgPC0gMC4xCmFjY2VwdGVkX25hbWVfY291bnRfc3BlY2llcyA8LSBDZXRhY2VhX29jY1tDZXRhY2VhX29jYyRhY2NlcHRlZF9yYW5rPT0ic3BlY2llcyIsXSRhY2NlcHRlZF9uYW1lX2NvdW50CmRlbnMgPC0gc2FwcGx5KDE6bWF4KGFjY2VwdGVkX25hbWVfY291bnRfc3BlY2llcyksIGZ1bmN0aW9uKG4peyBleHBlY3RlZF9kaXN0cmlidXRpb24obiwgb21lZ2EsIENldGFjZWFfb2NjW0NldGFjZWFfb2NjJGFjY2VwdGVkX3Jhbms9PSJzcGVjaWVzIixdJGFnZV9jb21iaW5lZF9yYW5nZSkkdmFsdWUgfSkKYWNjZXB0ZWRfbmFtZV9jb3VudF9jYXRlZ29yaWVzIDwtIHRhYmxlKGFjY2VwdGVkX25hbWVfY291bnRfc3BlY2llcykvYXMubnVtZXJpYyhuYW1lcyh0YWJsZShhY2NlcHRlZF9uYW1lX2NvdW50X3NwZWNpZXMpKSkgICMgTnVtYmVyIG9mIGNhdGVnb3JpZXMgd2l0aCAxLCAyLCAzLCAuLi4gb2NjdXJyZW5jZXMgb2YgdGhlIHNhbWUgc3BlY2llcwoKIyBDb21wYXJlIHRoZSBpbml0aWFsIG9ic2VydmVkIGRpc3RyaWJ1dGlvbiB3aXRoIHRoZSB0aGVvcmV0aWNhbCBjdXJ2ZQpnZ3Bsb3QoQ2V0YWNlYV9vY2NbQ2V0YWNlYV9vY2MkYWNjZXB0ZWRfcmFuaz09InNwZWNpZXMiLF0sIAogICAgICAgYWVzKHg9YWNjZXB0ZWRfbmFtZV9jb3VudCwgCiAgICAgICAgICAgeT1hY2NlcHRlZF9uYW1lX2NvdW50X2NhdGVnb3JpZXNbYXMuZmFjdG9yKGFjY2VwdGVkX25hbWVfY291bnQpXSwgCiAgICAgICAgICAgZmlsbD1hY2NlcHRlZF9yYW5rKSkgKwogIGdlb21fcG9pbnQoKSArCiAgCiAgYW5ub3RhdGUoImxpbmUiLCB4ID0gMTptYXgoYWNjZXB0ZWRfbmFtZV9jb3VudF9zcGVjaWVzKSwgeT0gZGVucwogICAgKm1heCgodGFibGUoYWNjZXB0ZWRfbmFtZV9jb3VudF9zcGVjaWVzKS9hcy5udW1lcmljKG5hbWVzKHRhYmxlKGFjY2VwdGVkX25hbWVfY291bnRfc3BlY2llcykpKSlbYXMuZmFjdG9yKGFjY2VwdGVkX25hbWVfY291bnRfc3BlY2llcyldKSAvbWF4KGRlbnMpKSsKICAKICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJOdW1iZXIgb2Ygb2NjdXJyZW5jZXMgYnkgYWNjZXB0ZWQgbmFtZSIpICsKICBzY2FsZV95X2NvbnRpbnVvdXModHJhbnMgPSAibG9nMTAiLCBuYW1lID0gIk51bWJlciBvZiBjb3JyZXNwb25kaW5nIGFjY2VwdGVkIG5hbWVzIChsb2ctc2NhbGUpIikgKwogIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZT0iT2JzZXJ2ZWQgZGlzdHJpYnV0aW9uIikgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpKSArCiAgZ2d0aXRsZSgiQ29tcGFyaXNvbiBiZXR3ZWVuIGV4cGVjdGVkIGFuZCBvYnNlcnZlZCBkaXN0cmlidXRpb25zIG9mIG51bWJlciBvZiBvY2N1cnJlbmNlcyIpICsKICBmYWNldF9ncmlkKGFjY2VwdGVkX3JhbmsgfiAuLCBzY2FsZXMgPSAiZnJlZSIpCgphY2NlcHRlZF9uYW1lX2NvdW50X3NwZWNpZXNfYWdncmVnIDwtIENldGFjZWFfb2NjX2FnZ3JlZ1tDZXRhY2VhX29jY19hZ2dyZWckYWNjZXB0ZWRfcmFuaz09InNwZWNpZXMiLF0kYWNjZXB0ZWRfbmFtZV9jb3VudApkZW5zX2FnZ3JlZyA8LSBzYXBwbHkoMTptYXgoYWNjZXB0ZWRfbmFtZV9jb3VudF9zcGVjaWVzX2FnZ3JlZyksIGZ1bmN0aW9uKG4pewogICAgIGV4cGVjdGVkX2Rpc3RyaWJ1dGlvbihuLCBvbWVnYSwgQ2V0YWNlYV9vY2NfYWdncmVnW0NldGFjZWFfb2NjX2FnZ3JlZyRhY2NlcHRlZF9yYW5rPT0ic3BlY2llcyIsXSRhZ2VfY29tYmluZWRfcmFuZ2UpJHZhbHVlCiAgICB9KQphY2NlcHRlZF9uYW1lX2NvdW50X2NhdGVnb3JpZXNfYWdncmVnIDwtIHRhYmxlKGFjY2VwdGVkX25hbWVfY291bnRfc3BlY2llc19hZ2dyZWcpL2FzLm51bWVyaWMobmFtZXModGFibGUoYWNjZXB0ZWRfbmFtZV9jb3VudF9zcGVjaWVzX2FnZ3JlZykpKSAgIyBOdW1iZXIgb2YgY2F0ZWdvcmllcyB3aXRoIDEsIDIsIDMsIC4uLiBvY2N1cnJlbmNlcyBvZiB0aGUgc2FtZSBzcGVjaWVzCgojIENvbXBhcmUgdGhlIGNvcnJlY3RlZCBvYnNlcnZlZCBkaXN0cmlidXRpb24gd2l0aCB0aGUgdGhlb3JldGljYWwgY3VydmUKZ2dwbG90KENldGFjZWFfb2NjX2FnZ3JlZ1tDZXRhY2VhX29jY19hZ2dyZWckYWNjZXB0ZWRfcmFuaz09InNwZWNpZXMiLF0sIAogICAgICAgYWVzKHg9YWNjZXB0ZWRfbmFtZV9jb3VudCwKICAgICAgICAgICB5PWFjY2VwdGVkX25hbWVfY291bnRfY2F0ZWdvcmllc19hZ2dyZWdbYXMuZmFjdG9yKGFjY2VwdGVkX25hbWVfY291bnQpXSwgCiAgICAgICAgICAgZmlsbD1hY2NlcHRlZF9yYW5rKSkgKwogIGdlb21fcG9pbnQoKSArCiAgCiAgYW5ub3RhdGUoImxpbmUiLCB4ID0gMTptYXgoYWNjZXB0ZWRfbmFtZV9jb3VudF9zcGVjaWVzX2FnZ3JlZyksIHk9IGRlbnNfYWdncmVnCiAgICAqbWF4KCh0YWJsZShhY2NlcHRlZF9uYW1lX2NvdW50X3NwZWNpZXNfYWdncmVnKS9hcy5udW1lcmljKG5hbWVzKHRhYmxlKGFjY2VwdGVkX25hbWVfY291bnRfc3BlY2llc19hZ2dyZWcpKSkpW2FzLmZhY3RvcihhY2NlcHRlZF9uYW1lX2NvdW50X3NwZWNpZXNfYWdncmVnKV0pIC9tYXgoZGVuc19hZ2dyZWcpKSArCiAgCiAgc2NhbGVfeF9jb250aW51b3VzKG5hbWUgPSAiTnVtYmVyIG9mIG9jY3VycmVuY2VzIGJ5IGFjY2VwdGVkIG5hbWUiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKHRyYW5zID0gImxvZzEwIiwgbmFtZSA9ICJOdW1iZXIgb2YgY29ycmVzcG9uZGluZyBhY2NlcHRlZCBuYW1lcyAobG9nLXNjYWxlKSIpICsKICBzY2FsZV9maWxsX2Rpc2NyZXRlKG5hbWU9Ik9ic2VydmVkIGRpc3RyaWJ1dGlvbiIpICsKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIGdndGl0bGUoIkNvbXBhcmlzb24gYmV0d2VlbiBleHBlY3RlZCBhbmQgb2JzZXJ2ZWQgZGlzdHJpYnV0aW9ucyBvZiBudW1iZXIgb2Ygb2NjdXJyZW5jZXMsIGFmdGVyIGFnZ3JlZ2F0aW5nIGluIGZvcm1hdGlvbnMiKSArCiAgZmFjZXRfZ3JpZChhY2NlcHRlZF9yYW5rIH4gLiwgc2NhbGVzID0gImZyZWUiKQoKYWNjZXB0ZWRfbmFtZV9jb3VudF9zcGVjaWVzX2FnZ3JlZyA8LSBDZXRhY2VhX29jY19hZ2dyZWdbQ2V0YWNlYV9vY2NfYWdncmVnJGFjY2VwdGVkX3Jhbms9PSJzcGVjaWVzIixdJGFjY2VwdGVkX25hbWVfY291bnQKZGVuc19hZ2dyZWcgPC0gc2FwcGx5KDE6bWF4KGFjY2VwdGVkX25hbWVfY291bnRfc3BlY2llc19hZ2dyZWcpLCBmdW5jdGlvbihuKXsKICAgICBleHBlY3RlZF9kaXN0cmlidXRpb24obiwgb21lZ2EsIENldGFjZWFfb2NjX2FnZ3JlZ1tDZXRhY2VhX29jY19hZ2dyZWckYWNjZXB0ZWRfcmFuaz09InNwZWNpZXMiLF0kYWdlX2NvbWJpbmVkX3JhbmdlKSR2YWx1ZQogICAgfSkKYWNjZXB0ZWRfbmFtZV9jb3VudF9jYXRlZ29yaWVzX2FnZ3JlZyA8LSB0YWJsZShhY2NlcHRlZF9uYW1lX2NvdW50X3NwZWNpZXNfYWdncmVnKS9hcy5udW1lcmljKG5hbWVzKHRhYmxlKGFjY2VwdGVkX25hbWVfY291bnRfc3BlY2llc19hZ2dyZWcpKSkgICMgTnVtYmVyIG9mIGNhdGVnb3JpZXMgd2l0aCAxLCAyLCAzLCAuLi4gb2NjdXJyZW5jZXMgb2YgdGhlIHNhbWUgc3BlY2llcwpgYGAKCiRcdG8kIFRoZSBiaWFzIGNhbiBiZSBjb3JyaWRlcmVkIGFzIGNvbXBsZXRlbHkgY29ycmVjdGVkLgoKYGBge3IgZmlnLmhlaWdodD02fQpjb25kaXRpb25zIDwtIENldGFjZWFfb2NjJGFjY2VwdGVkX3JhbmsgPT0ic3BlY2llcyIKCnAxIDwtIGdncGxvdChDZXRhY2VhX29jY1tjb25kaXRpb25zLF0sIGFlcyh4PS1hZ2VfcnVuaWYpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjUsIGFscGhhPTAuNSwgZmlsbD1OQSwgY29sPSJyZWQiKSArCiAgeGxpbSgtbWF4KENldGFjZWFfb2NjW2NvbmRpdGlvbnMsXSRhZ2VfcnVuaWYpLTEsIDEpICsKICB5bGltKDAsIDcwKSArCiAgdGhlbWVfdm9pZCgpCgpwMiA8LSBnZ3Bsb3QoQ2V0YWNlYV9vY2Nfc2FtcGxlZCwgYWVzKHg9LWFnZV9ydW5pZikpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuNSwgYWxwaGE9MC41LCBmaWxsPSJibHVlIikgKwogIHhsaW0oLW1heChDZXRhY2VhX29jY1tjb25kaXRpb25zLF0kYWdlX3J1bmlmKS0xLCAxKSArCiAgeWxpbSgwLCA3MCkgKwogIHRoZW1lX3ZvaWQoKQoKcDMgPC0gZ2dwbG90KENldGFjZWFfb2NjX2FnZ3JlZ1tDZXRhY2VhX29jY19hZ2dyZWckYWNjZXB0ZWRfcmFuayA9PSJzcGVjaWVzIixdLCBhZXMoeD0tYWdlX3J1bmlmKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC41LCBhbHBoYT0wLjUsIGZpbGw9ImdyZWVuIikgKwogIHhsaW0oLW1heChDZXRhY2VhX29jY1tjb25kaXRpb25zLF0kYWdlX3J1bmlmKS0xLCAxKSArCiAgeWxpbSgwLCA3MCkgKwogIHRoZW1lX3ZvaWQoKQoKcDEgKyBhbm5vdGF0aW9uX2N1c3RvbShnZ3Bsb3RHcm9iKHAyKSkgKyBnZ3RpdGxlKCJJbml0aWFsIG9jY3VycmVuY2VzIGRpc3RyaWJ1dGlvbiAocmVkKSBhbmQgY29tcGFyaXNvbiBhZnRlciBzdWItc2FtcGxpbmcgKGJsdWUpIikKCnAxICsgYW5ub3RhdGlvbl9jdXN0b20oZ2dwbG90R3JvYihwMykpICsgZ2d0aXRsZSgiSW5pdGlhbCBvY2N1cnJlbmNlcyBkaXN0cmlidXRpb24gKHJlZCkgYW5kIGNvbXBhcmlzb24gYWZ0ZXIgYWdncmVnYXRpbmcgaW4gZm9ybWF0aW9ucyAoZ3JlZW4pIikKCnAxICsgYW5ub3RhdGlvbl9jdXN0b20oZ2dwbG90R3JvYihwMikpICsgYW5ub3RhdGlvbl9jdXN0b20oZ2dwbG90R3JvYihwMykpICsgZ2d0aXRsZSgiSW5pdGlhbCBvY2N1cnJlbmNlcyBkaXN0cmlidXRpb24gKHJlZCkgYW5kIGNvbXBhcmlzb24gYWZ0ZXIgc3ViLXNhbXBsaW5nIChibHVlKSBvciBhZ2dyZWdhdGluZyBpbiBmb3JtYXRpb25zIChncmVlbikiKQpgYGAKCiRcdG8kIENvbXBhcmluZyB3aXRoIHRoZSBpbml0aWFsIG9jY3VycmVuY2VzIGRpc3RyaWJ1dGlvbiBhbmQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uIGFmdGVyIG91ciBmaXJzdCBzdWItc2FtcGxpbmcgaXQgYXBwZWFycyB0aGF0IGJvdGggbWV0aG9kcyBsZWFkIHRvIHZlcnkgc2ltaWxhciBkaXN0cmlidXRpb25zLiBUaGlzIGNvbmZvcnRzIHVzIGFib3V0IHRoZSByb2J1c3RuZXNzIG9mIHRob3NlIGFwcHJvYWNoZXMuCgpIb3dldmVyLCB3ZSBoYXZlIHRvIHRha2UgaW50byBhY2NvdW50IHRoZSBvY2N1cnJlbmNlcyB0aGF0IGRvIG5vdCBoYXZlIGFueSBpbmRpY2F0ZWQgZ2VvbG9naWNhbCBmb3JtYXRpb24gdG8gc3Vic2FtcGxlIHRoZW0gc2VwYXJhdGVseS4gVG8gYXBwcm94aW1hdGUgZ2VvbG9naWNhbCBmb3JtYXRpb24gd2UgY2hvc2UgdG8gcHJvY2VlZCB0byB0aGUgYWdncmVnYXRpb24gYmFzZWQgb24gdGhlIGNvbWJpbmF0aW9uIG9mIHRoZSBjb3VudHJ5IGFuZCB0aGUgZWFybHkgc3RyYXRpZ3JhcGhpYyBpbnRlcnZhbC4KCiMjIEFnZ3JlZ2F0ZSBvY2N1cnJlbmNlcyB3aXRob3V0IGZvcm1hdGlvbiBieSBjb3VudHJ5ICsgZWFybHkgaW50ZXJ2YWwKCmBgYHtyfQpDZXRhY2VhX29jY19hZ2dyZWcgPC0gYygpCgojIEJyb3dzZSBhbGwgY291bnRyaWVzCmNvdW50cmllcyA8LSBsZXZlbHMoZHJvcGxldmVscyhDZXRhY2VhX29jY1tDZXRhY2VhX29jYyRmb3JtYXRpb249PSIiLF0kY2MpKQpmb3IgKGNvdW50cnkgaW4gY291bnRyaWVzKXsKICBDZXRhY2VhX29jY19jYyA8LSBDZXRhY2VhX29jY1tDZXRhY2VhX29jYyRmb3JtYXRpb249PSIiICYgQ2V0YWNlYV9vY2MkY2M9PWNvdW50cnksXQogIAogICMgQnJvd3NlIGFsbCBlYXJseSBzdHJhdGlncmFwaGljIGludGVydmFscwogIGVhcmx5X2ludGVydmFscyA8LSBsZXZlbHMoZHJvcGxldmVscyhDZXRhY2VhX29jY19jYyRlYXJseV9pbnRlcnZhbCkpCiAgZm9yIChlaSBpbiBlYXJseV9pbnRlcnZhbHMpewogICAgQ2V0YWNlYV9vY2NfY2NfZWkgPC0gQ2V0YWNlYV9vY2NfY2NbQ2V0YWNlYV9vY2NfY2MkZWFybHlfaW50ZXJ2YWw9PWVpLF0KICAgIAogICAgIyBCcm93c2UgYWxsIGFjY2VwdGVkIG5hbWVzIGluIGVhY2ggY291bnRyeSAmIHNhbXBsZSBvbmx5IDEgb2NjdXJyZW5jZQogICAgdGF4YSA8LSBsZXZlbHMoZHJvcGxldmVscyhDZXRhY2VhX29jY19jY19laSRhY2NlcHRlZF9uYW1lKSkKICAgIGZvciAobmFtZSBpbiB0YXhhKXsKICAgICAgQ2V0YWNlYV9vY2NfYWdncmVnIDwtIHJiaW5kKENldGFjZWFfb2NjX2FnZ3JlZywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9uKENldGFjZWFfb2NjX2NjX2VpW0NldGFjZWFfb2NjX2NjX2VpJGFjY2VwdGVkX25hbWU9PW5hbWUsXSwgc2l6ZSA9IDEpKQogICAgfQogIH0KfQoKIyBCcm93c2UgYWxsIGZvcm1hdGlvbnMKZm9ybWF0aW9ucyA8LSBsZXZlbHMoZHJvcGxldmVscyhDZXRhY2VhX29jYyRmb3JtYXRpb24pKQpmb3IgKGZvcm0gaW4gZm9ybWF0aW9uc1std2hpY2goZm9ybWF0aW9ucz09IiIpXSl7CiAgQ2V0YWNlYV9vY2NfZm9ybSA8LSBDZXRhY2VhX29jY1tDZXRhY2VhX29jYyRmb3JtYXRpb249PWZvcm0sXQogIAogICMgQnJvd3NlIGFsbCBhY2NlcHRlZCBuYW1lcyBpbiBlYWNoIGZvcm1hdGlvbiAmIHNhbXBsZSBvbmx5IDEgb2NjdXJyZW5jZQogIHRheGEgPC0gbGV2ZWxzKGRyb3BsZXZlbHMoQ2V0YWNlYV9vY2NfZm9ybSRhY2NlcHRlZF9uYW1lKSkKICBmb3IgKG5hbWUgaW4gdGF4YSl7CiAgICBDZXRhY2VhX29jY19hZ2dyZWcgPC0gcmJpbmQoQ2V0YWNlYV9vY2NfYWdncmVnLCBzYW1wbGVfbihDZXRhY2VhX29jY19mb3JtW0NldGFjZWFfb2NjX2Zvcm0kYWNjZXB0ZWRfbmFtZT09bmFtZSxdLCBzaXplID0gMSkpCiAgfQp9CgpkYXRhLmZyYW1lKENldGFjZWFfb2NjID0gYyhkaW0oQ2V0YWNlYV9vY2MpWzFdLAogICAgICAgICAgICAgICAgICAgICAgICAgICBkaW0oQ2V0YWNlYV9vY2NbQ2V0YWNlYV9vY2MkYWNjZXB0ZWRfcmFuayA9PSJzcGVjaWVzIixdKVsxXSksCiAgICAgICAgICAgQ2V0YWNlYV9vY2NfYWdncmVnID0gYyhkaW0oQ2V0YWNlYV9vY2NfYWdncmVnKVsxXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbShDZXRhY2VhX29jY19hZ2dyZWdbQ2V0YWNlYV9vY2NfYWdncmVnJGFjY2VwdGVkX3JhbmsgPT0ic3BlY2llcyIsXSlbMV0pLAogICAgICAgICAgIHJlbW92ZWQgPSBjKGRpbShDZXRhY2VhX29jYylbMV0tZGltKENldGFjZWFfb2NjX2FnZ3JlZylbMV0sCiAgICAgICAgICAgICAgICAgICAgICAgZGltKENldGFjZWFfb2NjW0NldGFjZWFfb2NjJGFjY2VwdGVkX3JhbmsgPT0ic3BlY2llcyIsXSlbMV0tZGltKENldGFjZWFfb2NjX2FnZ3JlZ1tDZXRhY2VhX29jY19hZ2dyZWckYWNjZXB0ZWRfcmFuayA9PSJzcGVjaWVzIixdKVsxXSksCiAgICAgICAgICAgcm93Lm5hbWVzID0gYygiTnVtYmVyIG9mIG9jY3VycmVuY2VzIiwgIk51bWJlciBvZiBvY2N1cnJlbmNlcyAoc3BlY2llcyBvbmx5KSIpKQpgYGAKCk1vcmUgb2NjdXJyZW5jZXMgcmVtYWluIGFmdGVyIGFnZ3JlZ2F0aW5nIHdpdGggdGhpcyBuZXcgbWV0aG9kLiBMZXQncyBjb21wYXJlIGFnYWluIHdpdGggdGhlIHRoZW9yZXRpY2FsIGRpc3RyaWJ1dGlvbiA6CgpgYGB7ciBmaWcuaGVpZ2h0PTd9CiMgUmVjb3VudCB0aGUgbnVtYmVyIG9mIG9jY3VycmVuY2VzIHdpdGggdGhlIHNhbWUgYWNjZXB0ZWQgbmFtZSBhZnRlciB0aGUgYWdncmVnYXRpb24KQ2V0YWNlYV9vY2NfYWdncmVnJGFjY2VwdGVkX25hbWVfY291bnQgPC0gc2FwcGx5KENldGFjZWFfb2NjX2FnZ3JlZyRhY2NlcHRlZF9uYW1lLCBmdW5jdGlvbih4KXt0YWJsZShDZXRhY2VhX29jY19hZ2dyZWckYWNjZXB0ZWRfbmFtZSlbeF19KQoKb21lZ2EgPC0gMC4xNQphY2NlcHRlZF9uYW1lX2NvdW50X3NwZWNpZXMgPC0gQ2V0YWNlYV9vY2NbQ2V0YWNlYV9vY2MkYWNjZXB0ZWRfcmFuaz09InNwZWNpZXMiLF0kYWNjZXB0ZWRfbmFtZV9jb3VudApkZW5zIDwtIHNhcHBseSgxOm1heChhY2NlcHRlZF9uYW1lX2NvdW50X3NwZWNpZXMpLCBmdW5jdGlvbihuKXsgZXhwZWN0ZWRfZGlzdHJpYnV0aW9uKG4sIG9tZWdhLCBDZXRhY2VhX29jY1tDZXRhY2VhX29jYyRhY2NlcHRlZF9yYW5rPT0ic3BlY2llcyIsXSRhZ2VfY29tYmluZWRfcmFuZ2UpJHZhbHVlIH0pCmFjY2VwdGVkX25hbWVfY291bnRfY2F0ZWdvcmllcyA8LSB0YWJsZShhY2NlcHRlZF9uYW1lX2NvdW50X3NwZWNpZXMpL2FzLm51bWVyaWMobmFtZXModGFibGUoYWNjZXB0ZWRfbmFtZV9jb3VudF9zcGVjaWVzKSkpICAjIE51bWJlciBvZiBjYXRlZ29yaWVzIHdpdGggMSwgMiwgMywgLi4uIG9jY3VycmVuY2VzIG9mIHRoZSBzYW1lIHNwZWNpZXMKCiMgQ29tcGFyZSB0aGUgaW5pdGlhbCBvYnNlcnZlZCBkaXN0cmlidXRpb24gd2l0aCB0aGUgdGhlb3JldGljYWwgY3VydmUKZ2dwbG90KENldGFjZWFfb2NjW0NldGFjZWFfb2NjJGFjY2VwdGVkX3Jhbms9PSJzcGVjaWVzIixdLCAKICAgICAgIGFlcyh4PWFjY2VwdGVkX25hbWVfY291bnQsIAogICAgICAgICAgIHk9YWNjZXB0ZWRfbmFtZV9jb3VudF9jYXRlZ29yaWVzW2FzLmZhY3RvcihhY2NlcHRlZF9uYW1lX2NvdW50KV0sIAogICAgICAgICAgIGZpbGw9YWNjZXB0ZWRfcmFuaykpICsKICBnZW9tX3BvaW50KCkgKwogIAogIGFubm90YXRlKCJsaW5lIiwgeCA9IDE6bWF4KGFjY2VwdGVkX25hbWVfY291bnRfc3BlY2llcyksIHk9IGRlbnMKICAgICptYXgoKHRhYmxlKGFjY2VwdGVkX25hbWVfY291bnRfc3BlY2llcykvYXMubnVtZXJpYyhuYW1lcyh0YWJsZShhY2NlcHRlZF9uYW1lX2NvdW50X3NwZWNpZXMpKSkpW2FzLmZhY3RvcihhY2NlcHRlZF9uYW1lX2NvdW50X3NwZWNpZXMpXSkgL21heChkZW5zKSkrCiAgCiAgc2NhbGVfeF9jb250aW51b3VzKG5hbWUgPSAiTnVtYmVyIG9mIG9jY3VycmVuY2VzIGJ5IGFjY2VwdGVkIG5hbWUiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKHRyYW5zID0gImxvZzEwIiwgbmFtZSA9ICJOdW1iZXIgb2YgY29ycmVzcG9uZGluZyBhY2NlcHRlZCBuYW1lcyAobG9nLXNjYWxlKSIpICsKICBzY2FsZV9maWxsX2Rpc2NyZXRlKG5hbWU9Ik9ic2VydmVkIGRpc3RyaWJ1dGlvbiIpICsKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIGdndGl0bGUoIkNvbXBhcmlzb24gYmV0d2VlbiBleHBlY3RlZCBhbmQgb2JzZXJ2ZWQgZGlzdHJpYnV0aW9ucyBvZiBudW1iZXIgb2Ygb2NjdXJyZW5jZXMiKSArCiAgZmFjZXRfZ3JpZChhY2NlcHRlZF9yYW5rIH4gLiwgc2NhbGVzID0gImZyZWUiKQoKYWNjZXB0ZWRfbmFtZV9jb3VudF9zcGVjaWVzX2FnZ3JlZyA8LSBDZXRhY2VhX29jY19hZ2dyZWdbQ2V0YWNlYV9vY2NfYWdncmVnJGFjY2VwdGVkX3Jhbms9PSJzcGVjaWVzIixdJGFjY2VwdGVkX25hbWVfY291bnQKZGVuc19hZ2dyZWcgPC0gc2FwcGx5KDE6bWF4KGFjY2VwdGVkX25hbWVfY291bnRfc3BlY2llc19hZ2dyZWcpLCBmdW5jdGlvbihuKXsKICAgICBleHBlY3RlZF9kaXN0cmlidXRpb24obiwgb21lZ2EsIENldGFjZWFfb2NjX2FnZ3JlZ1tDZXRhY2VhX29jY19hZ2dyZWckYWNjZXB0ZWRfcmFuaz09InNwZWNpZXMiLF0kYWdlX2NvbWJpbmVkX3JhbmdlKSR2YWx1ZQogICAgfSkKYWNjZXB0ZWRfbmFtZV9jb3VudF9jYXRlZ29yaWVzX2FnZ3JlZyA8LSB0YWJsZShhY2NlcHRlZF9uYW1lX2NvdW50X3NwZWNpZXNfYWdncmVnKS9hcy5udW1lcmljKG5hbWVzKHRhYmxlKGFjY2VwdGVkX25hbWVfY291bnRfc3BlY2llc19hZ2dyZWcpKSkgICMgTnVtYmVyIG9mIGNhdGVnb3JpZXMgd2l0aCAxLCAyLCAzLCAuLi4gb2NjdXJyZW5jZXMgb2YgdGhlIHNhbWUgc3BlY2llcwoKIyBDb21wYXJlIHRoZSBjb3JyZWN0ZWQgb2JzZXJ2ZWQgZGlzdHJpYnV0aW9uIHdpdGggdGhlIHRoZW9yZXRpY2FsIGN1cnZlCmdncGxvdChDZXRhY2VhX29jY19hZ2dyZWdbQ2V0YWNlYV9vY2NfYWdncmVnJGFjY2VwdGVkX3Jhbms9PSJzcGVjaWVzIixdLCAKICAgICAgIGFlcyh4PWFjY2VwdGVkX25hbWVfY291bnQsCiAgICAgICAgICAgeT1hY2NlcHRlZF9uYW1lX2NvdW50X2NhdGVnb3JpZXNfYWdncmVnW2FzLmZhY3RvcihhY2NlcHRlZF9uYW1lX2NvdW50KV0sIAogICAgICAgICAgIGZpbGw9YWNjZXB0ZWRfcmFuaykpICsKICBnZW9tX3BvaW50KCkgKwogIAogIGFubm90YXRlKCJsaW5lIiwgeCA9IDE6bWF4KGFjY2VwdGVkX25hbWVfY291bnRfc3BlY2llc19hZ2dyZWcpLCB5PSBkZW5zX2FnZ3JlZwogICAgKm1heCgodGFibGUoYWNjZXB0ZWRfbmFtZV9jb3VudF9zcGVjaWVzX2FnZ3JlZykvYXMubnVtZXJpYyhuYW1lcyh0YWJsZShhY2NlcHRlZF9uYW1lX2NvdW50X3NwZWNpZXNfYWdncmVnKSkpKVthcy5mYWN0b3IoYWNjZXB0ZWRfbmFtZV9jb3VudF9zcGVjaWVzX2FnZ3JlZyldKSAvbWF4KGRlbnNfYWdncmVnKSkgKwogIAogIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIk51bWJlciBvZiBvY2N1cnJlbmNlcyBieSBhY2NlcHRlZCBuYW1lIikgKwogIHNjYWxlX3lfY29udGludW91cyh0cmFucyA9ICJsb2cxMCIsIG5hbWUgPSAiTnVtYmVyIG9mIGNvcnJlc3BvbmRpbmcgYWNjZXB0ZWQgbmFtZXMgKGxvZy1zY2FsZSkiKSArCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lPSJPYnNlcnZlZCBkaXN0cmlidXRpb24iKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCkpICsKICBnZ3RpdGxlKCJDb21wYXJpc29uIGJldHdlZW4gZXhwZWN0ZWQgYW5kIG9ic2VydmVkIGRpc3RyaWJ1dGlvbnMgb2YgbnVtYmVyIG9mIG9jY3VycmVuY2VzLCBhZnRlciBhZ2dyZWdhdGluZyBpbiBmb3JtYXRpb25zIikgKwogIGZhY2V0X2dyaWQoYWNjZXB0ZWRfcmFuayB+IC4sIHNjYWxlcyA9ICJmcmVlIikKCmFjY2VwdGVkX25hbWVfY291bnRfc3BlY2llc19hZ2dyZWcgPC0gQ2V0YWNlYV9vY2NfYWdncmVnW0NldGFjZWFfb2NjX2FnZ3JlZyRhY2NlcHRlZF9yYW5rPT0ic3BlY2llcyIsXSRhY2NlcHRlZF9uYW1lX2NvdW50CmRlbnNfYWdncmVnIDwtIHNhcHBseSgxOm1heChhY2NlcHRlZF9uYW1lX2NvdW50X3NwZWNpZXNfYWdncmVnKSwgZnVuY3Rpb24obil7CiAgICAgZXhwZWN0ZWRfZGlzdHJpYnV0aW9uKG4sIG9tZWdhLCBDZXRhY2VhX29jY19hZ2dyZWdbQ2V0YWNlYV9vY2NfYWdncmVnJGFjY2VwdGVkX3Jhbms9PSJzcGVjaWVzIixdJGFnZV9jb21iaW5lZF9yYW5nZSkkdmFsdWUKICAgIH0pCmFjY2VwdGVkX25hbWVfY291bnRfY2F0ZWdvcmllc19hZ2dyZWcgPC0gdGFibGUoYWNjZXB0ZWRfbmFtZV9jb3VudF9zcGVjaWVzX2FnZ3JlZykvYXMubnVtZXJpYyhuYW1lcyh0YWJsZShhY2NlcHRlZF9uYW1lX2NvdW50X3NwZWNpZXNfYWdncmVnKSkpICAjIE51bWJlciBvZiBjYXRlZ29yaWVzIHdpdGggMSwgMiwgMywgLi4uIG9jY3VycmVuY2VzIG9mIHRoZSBzYW1lIHNwZWNpZXMKYGBgCgokXHRvJCBUaGUgY29ycmVzcG9uZGFuY2UgaXMgc3RpbGwgZ29vZCwgZXhjZXB0IGZvciB0d28gdGF4YSA6CgpgYGB7cn0KdGFibGUoZHJvcGxldmVscyhDZXRhY2VhX29jY19hZ2dyZWdbQ2V0YWNlYV9vY2NfYWdncmVnJGFjY2VwdGVkX3Jhbms9PSJzcGVjaWVzIixdW2FjY2VwdGVkX25hbWVfY291bnRfc3BlY2llc19hZ2dyZWc+MTAsXSRhY2NlcHRlZF9uYW1lKSkKYGBgCgpgYGB7ciwgd2FybmluZz1GQUxTRX0KQ2V0YWNlYV9vY2NfYWdncmVnJGFnZV9yYW5nZSA8LSBDZXRhY2VhX29jY19hZ2dyZWckbWF4X21hLUNldGFjZWFfb2NjX2FnZ3JlZyRtaW5fbWEKQ2V0YWNlYV9vY2NfYWdncmVnJG1pbl9taW5fbWEgPC0gYXBwbHkoQ2V0YWNlYV9vY2NfYWdncmVnLCAxLCBmdW5jdGlvbihYKXttaW4oQ2V0YWNlYV9vY2NfYWdncmVnW0NldGFjZWFfb2NjX2FnZ3JlZyRhZ2VfcmFuZ2U8MTAgJiBDZXRhY2VhX29jY19hZ2dyZWckYWNjZXB0ZWRfbmFtZT09WFsiYWNjZXB0ZWRfbmFtZSJdLF0kbWluX21hKX0pCkNldGFjZWFfb2NjX2FnZ3JlZyRtYXhfbWF4X21hIDwtIGFwcGx5KENldGFjZWFfb2NjX2FnZ3JlZywgMSwgZnVuY3Rpb24oWCl7bWF4KENldGFjZWFfb2NjX2FnZ3JlZ1tDZXRhY2VhX29jY19hZ2dyZWckYWdlX3JhbmdlPDEwICYgQ2V0YWNlYV9vY2NfYWdncmVnJGFjY2VwdGVkX25hbWU9PVhbImFjY2VwdGVkX25hbWUiXSxdJG1heF9tYSl9KQpDZXRhY2VhX29jY19hZ2dyZWckYWdlX2NvbWJpbmVkX21lYW4gPC0gKENldGFjZWFfb2NjX2FnZ3JlZyRtaW5fbWluX21hICsgQ2V0YWNlYV9vY2NfYWdncmVnJG1heF9tYXhfbWEpLzIKQ2V0YWNlYV9vY2NfYWdncmVnJGFnZV9jb21iaW5lZF9yYW5nZSA8LSBDZXRhY2VhX29jY19hZ2dyZWckbWF4X21heF9tYS1DZXRhY2VhX29jY19hZ2dyZWckbWluX21pbl9tYQpDZXRhY2VhX29jY19hZ2dyZWckYWNjZXB0ZWRfbmFtZV9jb3VudCA8LSBzYXBwbHkoQ2V0YWNlYV9vY2NfYWdncmVnJGFjY2VwdGVkX25hbWUsIGZ1bmN0aW9uKHgpe3RhYmxlKENldGFjZWFfb2NjX2FnZ3JlZyRhY2NlcHRlZF9uYW1lKVt4XX0pCkNldGFjZWFfb2NjX2FnZ3JlZyRvY2N1cnJlbmNlX2NvbWJpbmVkX2RlbnNpdHkgPC0gQ2V0YWNlYV9vY2NfYWdncmVnJGFjY2VwdGVkX25hbWVfY291bnQvQ2V0YWNlYV9vY2NfYWdncmVnJGFnZV9jb21iaW5lZF9yYW5nZQpgYGAKCmBgYHtyIGZpZy5oZWlnaHQ9NSwgbWVzc2FnZT1GQUxTRX0KYnJlYWtzIDwtIGMoMC4xMjUsMC4yNSwwLjUsMSwyLDQsOCwxNikKCnBfYmVmb3JlIDwtIGdncGxvdChDZXRhY2VhX29jY1tDZXRhY2VhX29jYyRhY2NlcHRlZF9yYW5rID09InNwZWNpZXMiICYgQ2V0YWNlYV9vY2MkYWdlX3JhbmdlPDEwLF0sIGFlcyh4PS1tYXhfbWEsIHk9YWNjZXB0ZWRfbmFtZSkpICsKICBnZW9tX3NlZ21lbnQoYWVzKHggPSAtbWF4X21heF9tYSwgeSA9IHJlb3JkZXIoYWNjZXB0ZWRfbmFtZSwgLWFnZV9jb21iaW5lZF9tZWFuKSwgeGVuZCA9IC1taW5fbWluX21hLCB5ZW5kPXJlb3JkZXIoYWNjZXB0ZWRfbmFtZSwgLWFnZV9jb21iaW5lZF9tZWFuKSwgY29sb3I9b2NjdXJyZW5jZV9jb21iaW5lZF9kZW5zaXR5KSwgYXJyb3c9YXJyb3coZW5kcyA9ICJib3RoIiwgYW5nbGU9OTAsIGxlbmd0aCA9IHVuaXQoMSwgIm1tIikpLCBhbHBoYT0wLjUpICsKICBnZW9tX3BvaW50KGFlcyh4PS1hZ2VfcnVuaWYpLCBjb2w9InJlZCIsIGNleD0wLjUsIGFscGhhPTAuNSkgKwogIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIlRpbWUgKE15KSIpICsKICBzY2FsZV95X2Rpc2NyZXRlKG5hbWUgPSAiU3BlY2llcyIpICsKICBsYWJzKGNvbG91cj0iT2NjdXJyZW5jZVxuZGVuc2l0eSIpICsKICB0aGVtZShheGlzLnRleHQueT1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy55PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiLCBjb2xvciA9IE5BKSwKICAgICAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gInRyYW5zcGFyZW50IiwgY29sb3IgPSBOQSksCiAgICAgICAgbGVnZW5kLmJveC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiLCBjb2xvciA9IE5BKSkgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50bihjb2xvdXJzID0gYygiZGFya2JsdWUiLCAiZm9yZXN0Z3JlZW4iLCAiYmxhY2siKSwgdHJhbnM9ImxvZyIsIGJyZWFrcz1icmVha3MsIGxhYmVscz1icmVha3MpICsgCiAgZ2d0aXRsZShwYXN0ZSgiRGlzdHJpYnV0aW9ucyBvZiBzcGVjaWVzIGZvc3NpbCBhZ2UgcmFuZ2VzLCBiZWZvcmUgY29ycmVjdGluZyBzYW1wbGluZyAobiA9ICIsIGRpbShDZXRhY2VhX29jY1tDZXRhY2VhX29jYyRhY2NlcHRlZF9yYW5rID09InNwZWNpZXMiICYgQ2V0YWNlYV9vY2MkYWdlX3JhbmdlPDEwLF0pWzFdLCAiKSIsIHNlcD0iIikpCnBfYmVmb3JlCgpnZ3NhdmUoIkltYWdlcy9SYW5nZV9kaXN0cmlidXRpb25zX2JlZm9yZV9hZ2dyZWdhdGluZy5zdmciLCBwbG90ID0gcF9iZWZvcmUsIGRldmljZSA9ICJzdmciLCBiZyA9ICJ0cmFuc3BhcmVudCIpCgpwX2FmdGVyIDwtIGdncGxvdChDZXRhY2VhX29jY19hZ2dyZWdbQ2V0YWNlYV9vY2NfYWdncmVnJGFjY2VwdGVkX3JhbmsgPT0ic3BlY2llcyIgJiBDZXRhY2VhX29jY19hZ2dyZWckYWdlX3JhbmdlPDEwLF0sIGFlcyh4PS1tYXhfbWEsIHk9YWNjZXB0ZWRfbmFtZSkpICsKICBnZW9tX3NlZ21lbnQoYWVzKHggPSAtbWF4X21heF9tYSwgeSA9IHJlb3JkZXIoYWNjZXB0ZWRfbmFtZSwgLWFnZV9jb21iaW5lZF9tZWFuKSwgeGVuZCA9IC1taW5fbWluX21hLCB5ZW5kPXJlb3JkZXIoYWNjZXB0ZWRfbmFtZSwgLWFnZV9jb21iaW5lZF9tZWFuKSwgY29sb3I9b2NjdXJyZW5jZV9jb21iaW5lZF9kZW5zaXR5KSwgYXJyb3c9YXJyb3coZW5kcyA9ICJib3RoIiwgYW5nbGU9OTAsIGxlbmd0aCA9IHVuaXQoMSwgIm1tIikpLCBhbHBoYT0wLjUpICsKICBnZW9tX3BvaW50KGFlcyh4PS1hZ2VfcnVuaWYpLCBjb2w9InJlZCIsIGNleD0wLjUsIGFscGhhPTAuNSkgKwogIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIlRpbWUgKE15KSIpICsKICBzY2FsZV95X2Rpc2NyZXRlKG5hbWUgPSAiU3BlY2llcyIpICsKICBsYWJzKGNvbG91cj0iT2NjdXJyZW5jZVxuZGVuc2l0eSIpICsKICB0aGVtZShheGlzLnRleHQueT1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy55PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiLCBjb2xvciA9IE5BKSwKICAgICAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gInRyYW5zcGFyZW50IiwgY29sb3IgPSBOQSksCiAgICAgICAgbGVnZW5kLmJveC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiLCBjb2xvciA9IE5BKSkgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50bihjb2xvdXJzID0gYygiZGFya2JsdWUiLCAiZm9yZXN0Z3JlZW4iLCAiYmxhY2siKSwgdHJhbnM9ImxvZyIsIGJyZWFrcz1icmVha3MsIGxhYmVscz1icmVha3MpICsgCiAgZ2d0aXRsZShwYXN0ZSgiRGlzdHJpYnV0aW9ucyBvZiBzcGVjaWVzIGZvc3NpbCBhZ2UgcmFuZ2VzLCBhZnRlciBjb3JyZWN0aW5nIHNhbXBsaW5nIChuID0gIiwgZGltKENldGFjZWFfb2NjX3NhbXBsZWQpWzFdLCAiKSIsIHNlcD0iIikpCnBfYWZ0ZXIKCmdnc2F2ZSgiSW1hZ2VzL1JhbmdlX2Rpc3RyaWJ1dGlvbnNfYWZ0ZXJfYWdncmVnYXRpbmcuc3ZnIiwgcGxvdCA9IHBfYWZ0ZXIsIGRldmljZSA9ICJzdmciLCBiZyA9ICJ0cmFuc3BhcmVudCIpCmBgYAoKYGBge3IgZmlnLmhlaWdodD02LCBtZXNzYWdlPUZBTFNFfQpjb25kaXRpb25zIDwtIENldGFjZWFfb2NjJGFjY2VwdGVkX3JhbmsgPT0ic3BlY2llcyIKCnAxIDwtIGdncGxvdChDZXRhY2VhX29jY1tjb25kaXRpb25zLF0sIGFlcyh4PS1hZ2VfcnVuaWYpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjUsIGFscGhhPTAuNSwgZmlsbD1OQSwgY29sPSJyZWQiKSArCiAgeGxpbSgtbWF4KENldGFjZWFfb2NjW2NvbmRpdGlvbnMsXSRhZ2VfcnVuaWYpLTEsIDEpICsKICB5bGltKDAsIDcwKSArCiAgdGhlbWVfdm9pZCgpCgpwMiA8LSBnZ3Bsb3QoQ2V0YWNlYV9vY2Nfc2FtcGxlZCwgYWVzKHg9LWFnZV9ydW5pZikpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuNSwgYWxwaGE9MC41LCBmaWxsPSJibHVlIikgKwogIHhsaW0oLW1heChDZXRhY2VhX29jY1tjb25kaXRpb25zLF0kYWdlX3J1bmlmKS0xLCAxKSArCiAgeWxpbSgwLCA3MCkgKwogIHRoZW1lX3ZvaWQoKQoKcDMgPC0gZ2dwbG90KENldGFjZWFfb2NjX2FnZ3JlZ1tDZXRhY2VhX29jY19hZ2dyZWckYWNjZXB0ZWRfcmFuayA9PSJzcGVjaWVzIixdLCBhZXMoeD0tYWdlX3J1bmlmKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC41LCBhbHBoYT0wLjUsIGZpbGw9ImdyZWVuIikgKwogIHhsaW0oLW1heChDZXRhY2VhX29jY1tjb25kaXRpb25zLF0kYWdlX3J1bmlmKS0xLCAxKSArCiAgeWxpbSgwLCA3MCkgKwogIHRoZW1lX3ZvaWQoKQoKcDEgKyBhbm5vdGF0aW9uX2N1c3RvbShnZ3Bsb3RHcm9iKHAyKSkgKyBnZ3RpdGxlKCJJbml0aWFsIG9jY3VycmVuY2VzIGRpc3RyaWJ1dGlvbiAocmVkKSBhbmQgY29tcGFyaXNvbiBhZnRlciBzdWItc2FtcGxpbmcgKGJsdWUpIikKCnAxICsgYW5ub3RhdGlvbl9jdXN0b20oZ2dwbG90R3JvYihwMykpICsgZ2d0aXRsZSgiSW5pdGlhbCBvY2N1cnJlbmNlcyBkaXN0cmlidXRpb24gKHJlZCkgYW5kIGNvbXBhcmlzb24gYWZ0ZXIgYWdncmVnYXRpbmcgaW4gZm9ybWF0aW9ucyAoZ3JlZW4pIikKCnBfYWxsIDwtIHAxICsgYW5ub3RhdGlvbl9jdXN0b20oZ2dwbG90R3JvYihwMikpICsgYW5ub3RhdGlvbl9jdXN0b20oZ2dwbG90R3JvYihwMykpICsgZ2d0aXRsZSgiSW5pdGlhbCBvY2N1cnJlbmNlcyBkaXN0cmlidXRpb24gKHJlZCkgYW5kIGNvbXBhcmlzb24gYWZ0ZXIgc3ViLXNhbXBsaW5nIChibHVlKSBvciBhZ2dyZWdhdGluZyBpbiBmb3JtYXRpb25zIChncmVlbikiKSArIHRoZW1lKHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gInRyYW5zcGFyZW50IiwgY29sb3IgPSBOQSkpCnBfYWxsCgpnZ3NhdmUoIkltYWdlcy9PY2N1cnJlbmNlX2Rpc3RyaWJ1dGlvbnNfY29tcGFyaXNvbi5zdmciLCBwbG90ID0gcF9hbGwsIGRldmljZSA9ICJzdmciLCBiZyA9ICJ0cmFuc3BhcmVudCIpCmBgYAoKJFx0byQgQ29tcGFyaW5nIHdpdGggdGhlIGluaXRpYWwgb2NjdXJyZW5jZXMgZGlzdHJpYnV0aW9uIGFuZCB3aXRoIHRoZSBkaXN0cmlidXRpb24gYWZ0ZXIgb3VyIGZpcnN0IHN1Yi1zYW1wbGluZyBpdCBhcHBlYXJzIHRoYXQgYm90aCBtZXRob2RzIGxlYWQgdG8gdmVyeSBzaW1pbGFyIGRpc3RyaWJ1dGlvbnMuIFRoaXMgY29uZm9ydHMgdXMgYWJvdXQgdGhlIHJvYnVzdG5lc3Mgb2YgdGhvc2UgYXBwcm9hY2hlcy4KClJlcGxhY2luZyBjb3V0cmllcyBieSBnZWxvZ2ljYWwgcGxhdGVzIHNlZW1zIHRvIG1ha2UgbW9yZSBzZW5zIGZyb20gYSBwYWxhZW9udG9sb2dpY2FsIHBlcnNwZWN0aXZlLCBzbyBsZXQncyB0cnkgaXQuCgojIyBBZ2dyZWdhdGUgb2NjdXJyZW5jZXMgd2l0aG91dCBmb3JtYXRpb24gYnkgZ2VvcGxhdGUgKyBlYXJseSBpbnRlcnZhbAoKYGBge3J9CkNldGFjZWFfb2NjX2FnZ3JlZyA8LSBjKCkKCiMgQnJvd3NlIGFsbCBnZW9wbGF0ZXMKZ2VvcGxhdGVzIDwtIGxldmVscyhkcm9wbGV2ZWxzKENldGFjZWFfb2NjW0NldGFjZWFfb2NjJGZvcm1hdGlvbj09IiIsXSRnZW9wbGF0ZSkpCmZvciAoZ3AgaW4gZ2VvcGxhdGVzKXsKICBDZXRhY2VhX29jY19ncCA8LSBDZXRhY2VhX29jY1tDZXRhY2VhX29jYyRmb3JtYXRpb249PSIiICYgQ2V0YWNlYV9vY2MkZ2VvcGxhdGU9PWdwLF0KICAKICAjIEJyb3dzZSBhbGwgZWFybHkgc3RyYXRpZ3JhcGhpYyBpbnRlcnZhbHMKICBlYXJseV9pbnRlcnZhbHMgPC0gbGV2ZWxzKGRyb3BsZXZlbHMoQ2V0YWNlYV9vY2NfZ3AkZWFybHlfaW50ZXJ2YWwpKQogIGZvciAoZWkgaW4gZWFybHlfaW50ZXJ2YWxzKXsKICAgIENldGFjZWFfb2NjX2dwX2VpIDwtIENldGFjZWFfb2NjX2dwW0NldGFjZWFfb2NjX2dwJGVhcmx5X2ludGVydmFsPT1laSxdCiAgICAKICAgICMgQnJvd3NlIGFsbCBhY2NlcHRlZCBuYW1lcyAmIHNhbXBsZSBvbmx5IDEgb2NjdXJyZW5jZQogICAgdGF4YSA8LSBsZXZlbHMoZHJvcGxldmVscyhDZXRhY2VhX29jY19ncF9laSRhY2NlcHRlZF9uYW1lKSkKICAgIGZvciAobmFtZSBpbiB0YXhhKXsKICAgICAgQ2V0YWNlYV9vY2NfYWdncmVnIDwtIHJiaW5kKENldGFjZWFfb2NjX2FnZ3JlZywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9uKENldGFjZWFfb2NjX2dwX2VpW0NldGFjZWFfb2NjX2dwX2VpJGFjY2VwdGVkX25hbWU9PW5hbWUsXSwgc2l6ZSA9IDEpKQogICAgfQogIH0KfQoKIyBCcm93c2UgYWxsIGZvcm1hdGlvbnMKZm9ybWF0aW9ucyA8LSBsZXZlbHMoZHJvcGxldmVscyhDZXRhY2VhX29jYyRmb3JtYXRpb24pKQpmb3IgKGZvcm0gaW4gZm9ybWF0aW9uc1std2hpY2goZm9ybWF0aW9ucz09IiIpXSl7CiAgQ2V0YWNlYV9vY2NfZm9ybSA8LSBDZXRhY2VhX29jY1tDZXRhY2VhX29jYyRmb3JtYXRpb249PWZvcm0sXQogIAogICMgQnJvd3NlIGFsbCBhY2NlcHRlZCBuYW1lcyBpbiBlYWNoIGZvcm1hdGlvbiAmIHNhbXBsZSBvbmx5IDEgb2NjdXJyZW5jZQogIHRheGEgPC0gbGV2ZWxzKGRyb3BsZXZlbHMoQ2V0YWNlYV9vY2NfZm9ybSRhY2NlcHRlZF9uYW1lKSkKICBmb3IgKG5hbWUgaW4gdGF4YSl7CiAgICBDZXRhY2VhX29jY19hZ2dyZWcgPC0gcmJpbmQoQ2V0YWNlYV9vY2NfYWdncmVnLCBzYW1wbGVfbihDZXRhY2VhX29jY19mb3JtW0NldGFjZWFfb2NjX2Zvcm0kYWNjZXB0ZWRfbmFtZT09bmFtZSxdLCBzaXplID0gMSkpCiAgfQp9CgpkYXRhLmZyYW1lKENldGFjZWFfb2NjID0gYyhkaW0oQ2V0YWNlYV9vY2MpWzFdLAogICAgICAgICAgICAgICAgICAgICAgICAgICBkaW0oQ2V0YWNlYV9vY2NbQ2V0YWNlYV9vY2MkYWNjZXB0ZWRfcmFuayA9PSJzcGVjaWVzIixdKVsxXSksCiAgICAgICAgICAgQ2V0YWNlYV9vY2NfYWdncmVnID0gYyhkaW0oQ2V0YWNlYV9vY2NfYWdncmVnKVsxXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbShDZXRhY2VhX29jY19hZ2dyZWdbQ2V0YWNlYV9vY2NfYWdncmVnJGFjY2VwdGVkX3JhbmsgPT0ic3BlY2llcyIsXSlbMV0pLAogICAgICAgICAgIHJlbW92ZWQgPSBjKGRpbShDZXRhY2VhX29jYylbMV0tZGltKENldGFjZWFfb2NjX2FnZ3JlZylbMV0sCiAgICAgICAgICAgICAgICAgICAgICAgZGltKENldGFjZWFfb2NjW0NldGFjZWFfb2NjJGFjY2VwdGVkX3JhbmsgPT0ic3BlY2llcyIsXSlbMV0tZGltKENldGFjZWFfb2NjX2FnZ3JlZ1tDZXRhY2VhX29jY19hZ2dyZWckYWNjZXB0ZWRfcmFuayA9PSJzcGVjaWVzIixdKVsxXSksCiAgICAgICAgICAgcm93Lm5hbWVzID0gYygiTnVtYmVyIG9mIG9jY3VycmVuY2VzIiwgIk51bWJlciBvZiBvY2N1cnJlbmNlcyAoc3BlY2llcyBvbmx5KSIpKQpgYGAKCk1vcmUgb2NjdXJyZW5jZXMgcmVtYWluIGFmdGVyIGFnZ3JlZ2F0aW5nIHdpdGggdGhpcyBuZXcgbWV0aG9kLiBMZXQncyBjb21wYXJlIGFnYWluIHdpdGggdGhlIHRoZW9yZXRpY2FsIGRpc3RyaWJ1dGlvbiA6CgpgYGB7ciBmaWcuaGVpZ2h0PTd9CiMgUmVjb3VudCB0aGUgbnVtYmVyIG9mIG9jY3VycmVuY2VzIHdpdGggdGhlIHNhbWUgYWNjZXB0ZWQgbmFtZSBhZnRlciB0aGUgYWdncmVnYXRpb24KQ2V0YWNlYV9vY2NfYWdncmVnJGFjY2VwdGVkX25hbWVfY291bnQgPC0gc2FwcGx5KENldGFjZWFfb2NjX2FnZ3JlZyRhY2NlcHRlZF9uYW1lLCBmdW5jdGlvbih4KXt0YWJsZShDZXRhY2VhX29jY19hZ2dyZWckYWNjZXB0ZWRfbmFtZSlbeF19KQoKb21lZ2EgPC0gMC4xNQphY2NlcHRlZF9uYW1lX2NvdW50X3NwZWNpZXMgPC0gQ2V0YWNlYV9vY2NbQ2V0YWNlYV9vY2MkYWNjZXB0ZWRfcmFuaz09InNwZWNpZXMiLF0kYWNjZXB0ZWRfbmFtZV9jb3VudApkZW5zIDwtIHNhcHBseSgxOm1heChhY2NlcHRlZF9uYW1lX2NvdW50X3NwZWNpZXMpLCBmdW5jdGlvbihuKXsgZXhwZWN0ZWRfZGlzdHJpYnV0aW9uKG4sIG9tZWdhLCBDZXRhY2VhX29jY1tDZXRhY2VhX29jYyRhY2NlcHRlZF9yYW5rPT0ic3BlY2llcyIsXSRhZ2VfY29tYmluZWRfcmFuZ2UpJHZhbHVlIH0pCmFjY2VwdGVkX25hbWVfY291bnRfY2F0ZWdvcmllcyA8LSB0YWJsZShhY2NlcHRlZF9uYW1lX2NvdW50X3NwZWNpZXMpL2FzLm51bWVyaWMobmFtZXModGFibGUoYWNjZXB0ZWRfbmFtZV9jb3VudF9zcGVjaWVzKSkpICAjIE51bWJlciBvZiBjYXRlZ29yaWVzIHdpdGggMSwgMiwgMywgLi4uIG9jY3VycmVuY2VzIG9mIHRoZSBzYW1lIHNwZWNpZXMKCiMgQ29tcGFyZSB0aGUgaW5pdGlhbCBvYnNlcnZlZCBkaXN0cmlidXRpb24gd2l0aCB0aGUgdGhlb3JldGljYWwgY3VydmUKZ2dwbG90KENldGFjZWFfb2NjW0NldGFjZWFfb2NjJGFjY2VwdGVkX3Jhbms9PSJzcGVjaWVzIixdLCAKICAgICAgIGFlcyh4PWFjY2VwdGVkX25hbWVfY291bnQsIAogICAgICAgICAgIHk9YWNjZXB0ZWRfbmFtZV9jb3VudF9jYXRlZ29yaWVzW2FzLmZhY3RvcihhY2NlcHRlZF9uYW1lX2NvdW50KV0sIAogICAgICAgICAgIGZpbGw9YWNjZXB0ZWRfcmFuaykpICsKICBnZW9tX3BvaW50KCkgKwogIAogIGFubm90YXRlKCJsaW5lIiwgeCA9IDE6bWF4KGFjY2VwdGVkX25hbWVfY291bnRfc3BlY2llcyksIHk9IGRlbnMKICAgICptYXgoKHRhYmxlKGFjY2VwdGVkX25hbWVfY291bnRfc3BlY2llcykvYXMubnVtZXJpYyhuYW1lcyh0YWJsZShhY2NlcHRlZF9uYW1lX2NvdW50X3NwZWNpZXMpKSkpW2FzLmZhY3RvcihhY2NlcHRlZF9uYW1lX2NvdW50X3NwZWNpZXMpXSkgL21heChkZW5zKSkrCiAgCiAgc2NhbGVfeF9jb250aW51b3VzKG5hbWUgPSAiTnVtYmVyIG9mIG9jY3VycmVuY2VzIGJ5IGFjY2VwdGVkIG5hbWUiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKHRyYW5zID0gImxvZzEwIiwgbmFtZSA9ICJOdW1iZXIgb2YgY29ycmVzcG9uZGluZyBhY2NlcHRlZCBuYW1lcyAobG9nLXNjYWxlKSIpICsKICBzY2FsZV9maWxsX2Rpc2NyZXRlKG5hbWU9Ik9ic2VydmVkIGRpc3RyaWJ1dGlvbiIpICsKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIGdndGl0bGUoIkNvbXBhcmlzb24gYmV0d2VlbiBleHBlY3RlZCBhbmQgb2JzZXJ2ZWQgZGlzdHJpYnV0aW9ucyBvZiBudW1iZXIgb2Ygb2NjdXJyZW5jZXMiKSArCiAgZmFjZXRfZ3JpZChhY2NlcHRlZF9yYW5rIH4gLiwgc2NhbGVzID0gImZyZWUiKQoKYWNjZXB0ZWRfbmFtZV9jb3VudF9zcGVjaWVzX2FnZ3JlZyA8LSBDZXRhY2VhX29jY19hZ2dyZWdbQ2V0YWNlYV9vY2NfYWdncmVnJGFjY2VwdGVkX3Jhbms9PSJzcGVjaWVzIixdJGFjY2VwdGVkX25hbWVfY291bnQKZGVuc19hZ2dyZWcgPC0gc2FwcGx5KDE6bWF4KGFjY2VwdGVkX25hbWVfY291bnRfc3BlY2llc19hZ2dyZWcpLCBmdW5jdGlvbihuKXsKICAgICBleHBlY3RlZF9kaXN0cmlidXRpb24obiwgb21lZ2EsIENldGFjZWFfb2NjX2FnZ3JlZ1tDZXRhY2VhX29jY19hZ2dyZWckYWNjZXB0ZWRfcmFuaz09InNwZWNpZXMiLF0kYWdlX2NvbWJpbmVkX3JhbmdlKSR2YWx1ZQogICAgfSkKYWNjZXB0ZWRfbmFtZV9jb3VudF9jYXRlZ29yaWVzX2FnZ3JlZyA8LSB0YWJsZShhY2NlcHRlZF9uYW1lX2NvdW50X3NwZWNpZXNfYWdncmVnKS9hcy5udW1lcmljKG5hbWVzKHRhYmxlKGFjY2VwdGVkX25hbWVfY291bnRfc3BlY2llc19hZ2dyZWcpKSkgICMgTnVtYmVyIG9mIGNhdGVnb3JpZXMgd2l0aCAxLCAyLCAzLCAuLi4gb2NjdXJyZW5jZXMgb2YgdGhlIHNhbWUgc3BlY2llcwoKIyBDb21wYXJlIHRoZSBjb3JyZWN0ZWQgb2JzZXJ2ZWQgZGlzdHJpYnV0aW9uIHdpdGggdGhlIHRoZW9yZXRpY2FsIGN1cnZlCmdncGxvdChDZXRhY2VhX29jY19hZ2dyZWdbQ2V0YWNlYV9vY2NfYWdncmVnJGFjY2VwdGVkX3Jhbms9PSJzcGVjaWVzIixdLCAKICAgICAgIGFlcyh4PWFjY2VwdGVkX25hbWVfY291bnQsCiAgICAgICAgICAgeT1hY2NlcHRlZF9uYW1lX2NvdW50X2NhdGVnb3JpZXNfYWdncmVnW2FzLmZhY3RvcihhY2NlcHRlZF9uYW1lX2NvdW50KV0sIAogICAgICAgICAgIGZpbGw9YWNjZXB0ZWRfcmFuaykpICsKICBnZW9tX3BvaW50KCkgKwogIAogIGFubm90YXRlKCJsaW5lIiwgeCA9IDE6bWF4KGFjY2VwdGVkX25hbWVfY291bnRfc3BlY2llc19hZ2dyZWcpLCB5PSBkZW5zX2FnZ3JlZwogICAgKm1heCgodGFibGUoYWNjZXB0ZWRfbmFtZV9jb3VudF9zcGVjaWVzX2FnZ3JlZykvYXMubnVtZXJpYyhuYW1lcyh0YWJsZShhY2NlcHRlZF9uYW1lX2NvdW50X3NwZWNpZXNfYWdncmVnKSkpKVthcy5mYWN0b3IoYWNjZXB0ZWRfbmFtZV9jb3VudF9zcGVjaWVzX2FnZ3JlZyldKSAvbWF4KGRlbnNfYWdncmVnKSkgKwogIAogIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIk51bWJlciBvZiBvY2N1cnJlbmNlcyBieSBhY2NlcHRlZCBuYW1lIikgKwogIHNjYWxlX3lfY29udGludW91cyh0cmFucyA9ICJsb2cxMCIsIG5hbWUgPSAiTnVtYmVyIG9mIGNvcnJlc3BvbmRpbmcgYWNjZXB0ZWQgbmFtZXMgKGxvZy1zY2FsZSkiKSArCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lPSJPYnNlcnZlZCBkaXN0cmlidXRpb24iKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCkpICsKICBnZ3RpdGxlKCJDb21wYXJpc29uIGJldHdlZW4gZXhwZWN0ZWQgYW5kIG9ic2VydmVkIGRpc3RyaWJ1dGlvbnMgb2YgbnVtYmVyIG9mIG9jY3VycmVuY2VzLCBhZnRlciBhZ2dyZWdhdGluZyBpbiBnZW9wbGF0ZXMiKSArCiAgZmFjZXRfZ3JpZChhY2NlcHRlZF9yYW5rIH4gLiwgc2NhbGVzID0gImZyZWUiKQoKYWNjZXB0ZWRfbmFtZV9jb3VudF9zcGVjaWVzX2FnZ3JlZyA8LSBDZXRhY2VhX29jY19hZ2dyZWdbQ2V0YWNlYV9vY2NfYWdncmVnJGFjY2VwdGVkX3Jhbms9PSJzcGVjaWVzIixdJGFjY2VwdGVkX25hbWVfY291bnQKZGVuc19hZ2dyZWcgPC0gc2FwcGx5KDE6bWF4KGFjY2VwdGVkX25hbWVfY291bnRfc3BlY2llc19hZ2dyZWcpLCBmdW5jdGlvbihuKXsKICAgICBleHBlY3RlZF9kaXN0cmlidXRpb24obiwgb21lZ2EsIENldGFjZWFfb2NjX2FnZ3JlZ1tDZXRhY2VhX29jY19hZ2dyZWckYWNjZXB0ZWRfcmFuaz09InNwZWNpZXMiLF0kYWdlX2NvbWJpbmVkX3JhbmdlKSR2YWx1ZQogICAgfSkKYWNjZXB0ZWRfbmFtZV9jb3VudF9jYXRlZ29yaWVzX2FnZ3JlZyA8LSB0YWJsZShhY2NlcHRlZF9uYW1lX2NvdW50X3NwZWNpZXNfYWdncmVnKS9hcy5udW1lcmljKG5hbWVzKHRhYmxlKGFjY2VwdGVkX25hbWVfY291bnRfc3BlY2llc19hZ2dyZWcpKSkgICMgTnVtYmVyIG9mIGNhdGVnb3JpZXMgd2l0aCAxLCAyLCAzLCAuLi4gb2NjdXJyZW5jZXMgb2YgdGhlIHNhbWUgc3BlY2llcwpgYGAKCiRcdG8kIFRoZSBjb3JyZXNwb25kYW5jZSBpcyBzdGlsbCBnb29kLCBleGNlcHQgZm9yIHR3byB0YXhhIDoKCmBgYHtyfQp0YWJsZShkcm9wbGV2ZWxzKENldGFjZWFfb2NjX2FnZ3JlZ1tDZXRhY2VhX29jY19hZ2dyZWckYWNjZXB0ZWRfcmFuaz09InNwZWNpZXMiLF1bYWNjZXB0ZWRfbmFtZV9jb3VudF9zcGVjaWVzX2FnZ3JlZz4xMCxdJGFjY2VwdGVkX25hbWUpKQpgYGAKCmBgYHtyIGZpZy5oZWlnaHQ9Nn0KY29uZGl0aW9ucyA8LSBDZXRhY2VhX29jYyRhY2NlcHRlZF9yYW5rID09InNwZWNpZXMiCgpwMSA8LSBnZ3Bsb3QoQ2V0YWNlYV9vY2NbY29uZGl0aW9ucyxdLCBhZXMoeD0tYWdlX3J1bmlmKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC41LCBhbHBoYT0wLjUsIGZpbGw9TkEsIGNvbD0icmVkIikgKwogIHhsaW0oLW1heChDZXRhY2VhX29jY1tjb25kaXRpb25zLF0kYWdlX3J1bmlmKS0xLCAxKSArCiAgeWxpbSgwLCA3MCkgKwogIHRoZW1lX3ZvaWQoKQoKcDIgPC0gZ2dwbG90KENldGFjZWFfb2NjX3NhbXBsZWQsIGFlcyh4PS1hZ2VfcnVuaWYpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjUsIGFscGhhPTAuNSwgZmlsbD0iYmx1ZSIpICsKICB4bGltKC1tYXgoQ2V0YWNlYV9vY2NbY29uZGl0aW9ucyxdJGFnZV9ydW5pZiktMSwgMSkgKwogIHlsaW0oMCwgNzApICsKICB0aGVtZV92b2lkKCkKCnAzIDwtIGdncGxvdChDZXRhY2VhX29jY19hZ2dyZWdbQ2V0YWNlYV9vY2NfYWdncmVnJGFjY2VwdGVkX3JhbmsgPT0ic3BlY2llcyIsXSwgYWVzKHg9LWFnZV9ydW5pZikpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuNSwgYWxwaGE9MC41LCBmaWxsPSJncmVlbiIpICsKICB4bGltKC1tYXgoQ2V0YWNlYV9vY2NbY29uZGl0aW9ucyxdJGFnZV9ydW5pZiktMSwgMSkgKwogIHlsaW0oMCwgNzApICsKICB0aGVtZV92b2lkKCkKCnAxICsgYW5ub3RhdGlvbl9jdXN0b20oZ2dwbG90R3JvYihwMikpICsgZ2d0aXRsZSgiSW5pdGlhbCBvY2N1cnJlbmNlcyBkaXN0cmlidXRpb24gKHJlZCkgYW5kIGNvbXBhcmlzb24gYWZ0ZXIgc3ViLXNhbXBsaW5nIChibHVlKSIpCgpwMSArIGFubm90YXRpb25fY3VzdG9tKGdncGxvdEdyb2IocDMpKSArIGdndGl0bGUoIkluaXRpYWwgb2NjdXJyZW5jZXMgZGlzdHJpYnV0aW9uIChyZWQpIGFuZCBjb21wYXJpc29uIGFmdGVyIGFnZ3JlZ2F0aW5nIGluIGdlb3BsYXRlcyAoZ3JlZW4pIikKCnAxICsgYW5ub3RhdGlvbl9jdXN0b20oZ2dwbG90R3JvYihwMikpICsgYW5ub3RhdGlvbl9jdXN0b20oZ2dwbG90R3JvYihwMykpICsgZ2d0aXRsZSgiSW5pdGlhbCBvY2N1cnJlbmNlcyBkaXN0cmlidXRpb24gKHJlZCkgYW5kIGNvbXBhcmlzb24gYWZ0ZXIgc3ViLXNhbXBsaW5nIChibHVlKSBvciBhZ2dyZWdhdGluZyBpbiBnZW9wbGF0ZXMgKGdyZWVuKSIpCmBgYAoKJFx0byQgRGVsaW1pdGluZyBieSBnZW9sb2dpY2FsIHBsYXRlcyAoKyBhZ2UpIGluc3RlYWQgb2YgY291bnRyaWVzICgrIGFnZSkgbGVhZHMgdG8gc2ltaWxhciBkaXN0cmlidXRpb25zLCBzbyB3ZSB3aWxsIGtlZXAgaXQuCgojIyBDaGVjayB0aGF0IHRoZSBzYW1wbGluZyBtZXRob2RzIGRvIG5vdCBpbnRyb2R1Y2UgYmlhc2VzIGluIHRoZSByZXBhcnRpdGlvbiBiZXR3ZWVuIE9kb250b2NldGkgYW5kIE15c3RpY2V0aQoKTXlzdGVjZXRlcyBhcmUgdXN1YWxseSBsYXJnZXIgdGhhbiBvZG9udG9jZXRlcywgYW5kIHNpemUgaXMgYXNzb2NpYXRlZCB3aXRoIGEgd2lkZXIgZ2VvZ3JhcGhpYyByYW5nZSBzbyBzaW5jZSB3ZSBhcmUgc3Vic2FtcGxpbmcgb2NjdXJyZW5jZXMgYWNjb3JkaW5nIHRvIGdlb2xvZ2ljYWwgZm9ybWF0aW9uIHdlIG1heSBiZSBiaWFzaW5nIG91ciBkYXRhIHRvd2FyZHMgbW9yZSB3aWRlc3ByZWFkIHNwZWNpZXMsIHRoZXJlZm9yZSB0b3dhcmRzIG15c3RlY2V0ZXMuCgpMb29rIGF0IHRoZSBmYW1pbGllcyBmaXJzdCA6CgpgYGB7ciBmaWcuaGVpZ2h0PTZ9CmZhbWlsaWVzIDwtIHJiaW5kKENldGFjZWFfb2NjID0gQ2V0YWNlYV9vY2NbQ2V0YWNlYV9vY2MkYWNjZXB0ZWRfcmFuaz09InNwZWNpZXMiLF0sCiAgICAgICAgICAgICAgICAgIENldGFjZWFfb2NjX3NhbXBsZWQgPSBDZXRhY2VhX29jY19zYW1wbGVkLAogICAgICAgICAgICAgICAgICBDZXRhY2VhX29jY19hZ2dyZWcgPSBDZXRhY2VhX29jY19hZ2dyZWdbQ2V0YWNlYV9vY2NfYWdncmVnJGFjY2VwdGVkX3Jhbms9PSJzcGVjaWVzIixdKSAlPiUKICAgICAgICAgICAgdGliYmxlOjpyb3duYW1lc190b19jb2x1bW4odmFyID0gIkRhdGFzZXQiKQoKZmFtaWxpZXMgPC0gZmFtaWxpZXNbLGMoIkRhdGFzZXQiLCAiZmFtaWx5IildCmZhbWlsaWVzJERhdGFzZXQgPC0gc2FwcGx5KGZhbWlsaWVzJERhdGFzZXQsIGdzdWIsIHBhdHRlcm49IlxcLi4qIiwgcmVwbGFjZW1lbnQ9IiIpCgpnZ3Bsb3QoZmFtaWxpZXNbZmFtaWxpZXMkZmFtaWx5ICE9ICJOT19GQU1JTFlfU1BFQ0lGSUVEIixdLCBhZXMoeCA9IERhdGFzZXQsIGZpbGwgPSBmYW1pbHkpKSArIAogICAgZ2VvbV9iYXIocG9zaXRpb249ImZpbGwiLCBjb2w9ImJsYWNrIikKYGBgCgokXHRvJCBUaGUgZmFtaWx5IHJlcGFydGl0aW9ucyB2YXJ5IGEgYml0IGFmdGVyIHN1YnNhbXBsaW5nLCBidXQgYmVjYXVzZSBvZiB0aGUgbGltaXRlZCBudW1iZXIgb2Ygc3BlY2llcyBieSBmYW1pbHkgdGhlIGZhY3QgdGhhdCB3ZSBjb3JyZWN0ZWQgdGhlIG92ZXJzYW1wbGluZyBvZiBzb21lIHNwZWNpZXMgY291bGQgaGF2ZSBhIGRpc3Byb3BvcnRpb25hdGUgZWZmZWN0LgoKTGV0J3MgbG9vayByYXRoZXIgYXQgYSBoaWdoZXIgdGF4b25vbWljIHJhbmssIGJ5IGltcG9ydGluZyB0aGUgdG9wb2xvZ3kgb2YgY2V0YWNlYW4gZmFtaWxpZXMgKGZyb20gTWFyeCBldCBhbC4gMjAxNikgOgoKYGBge3IgZmlnLndpZHRoPTEwfQpmYW1pbGllc190cmVlIDwtIGFwZTo6cmVhZC50cmVlKCJiam9lbGxlLXN0cmF0aWdyYXBoaWNfYWdlX3VuY2VydGFpbnR5X1NJLTliYmNlZjIvY2V0YWNlYW5zX2RhdGEvZm9zc2lscy9mYW1pbGllcy50cmUiKQpnZ3RyZWUoZmFtaWxpZXNfdHJlZSkgKwogIGdlb21fdGlwbGFiKCkgKwogIGdlb21fbm9kZWxhYigpICsgCiAgZ2d0aXRsZSgiVG9wb2xvZ3kgb2YgY2V0YWNlYW4gZmFtaWxpZXMiKSArCiAgeGxpbSgwLCA4KQoKZmFtaWxpZXNfdHJlZV9PZG9udG9jZXRpIDwtIGNhc3Rvcjo6Z2V0X3N1YnRyZWVfYXRfbm9kZShmYW1pbGllc190cmVlLCAiT2RvbnRvY2V0aSIpJHN1YnRyZWUKZ2d0cmVlKGZhbWlsaWVzX3RyZWVfT2RvbnRvY2V0aSkgKwogIGdlb21fdGlwbGFiKCkgKwogIGdlb21fbm9kZWxhYigpICsgCiAgZ2d0aXRsZSgiVG9wb2xvZ3kgb2Ygb2RvbnRvY2V0ZSBmYW1pbGllcyIpICsKICB4bGltKDAsIDUpCgpmYW1pbGllc190cmVlX015c3RpY2V0aSA8LSBjYXN0b3I6OmdldF9zdWJ0cmVlX2F0X25vZGUoZmFtaWxpZXNfdHJlZSwgIk15c3RpY2V0aSIpJHN1YnRyZWUKZ2d0cmVlKGZhbWlsaWVzX3RyZWVfTXlzdGljZXRpKSArCiAgZ2VvbV90aXBsYWIoKSArCiAgZ2VvbV9ub2RlbGFiKCkgKyAKICBnZ3RpdGxlKCJUb3BvbG9neSBvZiBteXN0aWNldGUgZmFtaWxpZXMiKSArCiAgeGxpbSgwLCA1KQoKZmFtaWxpZXNfdHJlZV9TdGVtIDwtIGNhc3Rvcjo6Z2V0X3N1YnRyZWVfd2l0aF90aXBzKGZhbWlsaWVzX3RyZWUsIG9taXRfdGlwcyA9IGMoZmFtaWxpZXNfdHJlZV9PZG9udG9jZXRpJHRpcC5sYWJlbCwgZmFtaWxpZXNfdHJlZV9NeXN0aWNldGkkdGlwLmxhYmVsKSkkc3VidHJlZQpnZ3RyZWUoZmFtaWxpZXNfdHJlZV9TdGVtKSArCiAgZ2VvbV90aXBsYWIoKSArCiAgZ2VvbV9ub2RlbGFiKCkgKyAKICBnZ3RpdGxlKCJUb3BvbG9neSBvZiBhcmNoZW9jZXRlIGZhbWlsaWVzIikgKwogIHhsaW0oMCwgMykKYGBgCgpgYGB7cn0KT2RvbnRvY2V0aV9mYW1pbGllcyA8LSBjKGZhbWlsaWVzX3RyZWVfT2RvbnRvY2V0aVtjKCJ0aXAubGFiZWwiLCAibm9kZS5sYWJlbCIpXSwgIktlbnRyaW9kb250aWRhZSIsICJTcXVhbG96aXBoaWlkYWUiKQpNeXN0aWNldGlfZmFtaWxpZXMgPC0gZmFtaWxpZXNfdHJlZV9NeXN0aWNldGlbYygidGlwLmxhYmVsIiwgIm5vZGUubGFiZWwiKV0KYXJjaGFlb2NldGVfZmFtaWxpZXMgPC0gZmFtaWxpZXNfdHJlZV9TdGVtW2MoInRpcC5sYWJlbCIsICJub2RlLmxhYmVsIildCgpmYW1pbHlfdG9fdGF4b25vbWljX2dyb3VwIDwtIGZ1bmN0aW9uKGZhbWlseSl7CiAgcmV0dXJuKGMoIk9kb250b2NldGkiLCAiTXlzdGljZXRpIiwgImFyY2hhZW9jZXRlcyIpWwogICAgZ3JlcChwYXR0ZXJuID0gZmFtaWx5LAogICAgICAgICB4ID0gbGlzdChPZG9udG9jZXRpX2ZhbWlsaWVzLCBNeXN0aWNldGlfZmFtaWxpZXMsIGFyY2hhZW9jZXRlX2ZhbWlsaWVzKSldKQogIH0KCmZhbWlsaWVzJFRheG9ub21pYy5ncm91cCA8LSBhcy5jaGFyYWN0ZXIoc2FwcGx5KGZhbWlsaWVzJGZhbWlseSwgZmFtaWx5X3RvX3RheG9ub21pY19ncm91cCkpCmdncGxvdChmYW1pbGllc1tmYW1pbGllcyRmYW1pbHkgIT0gIk5PX0ZBTUlMWV9TUEVDSUZJRUQiLF0sIGFlcyh4ID0gRGF0YXNldCwgZmlsbCA9IFRheG9ub21pYy5ncm91cCkpICsgCiAgICBnZW9tX2Jhcihwb3NpdGlvbj0iZmlsbCIsIGNvbD0iYmxhY2siKQoKZ2dwbG90KGZhbWlsaWVzW2ZhbWlsaWVzJGZhbWlseSAhPSAiTk9fRkFNSUxZX1NQRUNJRklFRCIgJiBmYW1pbGllcyRUYXhvbm9taWMuZ3JvdXAgIT0gImFyY2hhZW9jZXRlcyIsXSwgYWVzKHggPSBEYXRhc2V0LCBmaWxsID0gVGF4b25vbWljLmdyb3VwKSkgKwogIGdlb21fYmFyKHBvc2l0aW9uPSJmaWxsIiwgY29sPSJibGFjayIpCmBgYAoKJFx0byQgVGhlcmUgaXMgYSBzbWFsbGVyIHByb3BvcnRpb24gb2YgYXJjaGVvY2V0ZSBvY2N1cnJlbmNlcyBhZnRlciBlaXRoZXIgc2FtcGxpbmcsIGJlY2F1c2UgYSBodWdlIGNsdXN0ZXIgaXMgc3Vic2FtcGxlZCBhcm91bmQgMzUgTXkgYWdvLCBidXQgdGhpcyBlZmZlY3QgaXMgZXhwZWN0ZWQuIEhvd2V2ZXIsIGZvciB0aGUgTXlzdGljZXRpIHZzLiBPZG90b2NldGkgdGhlcmUgaXMgbm8gaHVnZSBhcHBhcmVudCBiaWFzLCBlc3BlY2lhbGx5IHdpdGggdGhlIGFnZ3JlZ2F0aW5nIG1ldGhvZC4KCmBgYHtyfQojIHdyaXRlKENldGFjZWFfb2NjX2FnZ3JlZ1tDZXRhY2VhX29jY19hZ2dyZWckYWNjZXB0ZWRfcmFuayA9PSJzcGVjaWVzIixdJGFnZV9ydW5pZiwgCiMgICAgICAgZmlsZSA9ICJkYXRhLWNldGFjZWFucy9DZXRhY2VhX2FnZV9ydW5pZl9hZ2Vfc3BlY2llc19jb3JyZWN0ZWQuY3N2IiwgCiMgICAgICAgc2VwID0gIjsgIiwgCiMgICAgICAgbmNvbHVtbnMgPSBkaW0oQ2V0YWNlYV9vY2NfYWdncmVnW0NldGFjZWFfb2NjX2FnZ3JlZyRhY2NlcHRlZF9yYW5rID09InNwZWNpZXMiLF0pWzFdKQp3cml0ZS50YWJsZShDZXRhY2VhX29jY19hZ2dyZWdbQ2V0YWNlYV9vY2NfYWdncmVnJGFjY2VwdGVkX3JhbmsgJWluJSBjKCJzcGVjaWVzIiwgImdlbnVzIiksIGMoIm1pbl9tYSIsICJtYXhfbWEiKV0sCiAgICAgICAgICAgIGZpbGU9ImRhdGEtY2V0YWNlYW5zL0NldGFjZWFfb2NjdXJyZW5jZXNfbWluX21heF9hZ2Vfc3BlY2llc19jb3JyZWN0ZWQuY3N2Iiwgc2VwPSIsIiwgcm93Lm5hbWVzPUZBTFNFLCBjb2wubmFtZXM9RkFMU0UpCmBgYAoKIyBGYXN0ZXIgZ2VudXMtbGV2ZWwgYW5hbHlzaXMKCmBgYHtyfQpDZXRhY2VhX29jY19hZ2dyZWdfZ2VuIDwtIGMoKQoKIyBCcm93c2UgYWxsIGZvcm1hdGlvbnMKZm9ybWF0aW9ucyA8LSBsZXZlbHMoZHJvcGxldmVscyhDZXRhY2VhX29jYyRmb3JtYXRpb24pKQpmb3IgKGZvcm0gaW4gZm9ybWF0aW9uc1std2hpY2goZm9ybWF0aW9ucz09IiIpXSl7CiAgQ2V0YWNlYV9vY2NfZm9ybSA8LSBDZXRhY2VhX29jY1tDZXRhY2VhX29jYyRmb3JtYXRpb249PWZvcm0sXQogIAogICMgQnJvd3NlIGFsbCBnZW5lcmEgaW4gZWFjaCBmb3JtYXRpb24gJiBzYW1wbGUgb25seSAxIG9jY3VycmVuY2UKICBnZW5lcmEgPC0gbGV2ZWxzKGRyb3BsZXZlbHMoQ2V0YWNlYV9vY2NfZm9ybSRnZW51cykpCiAgZm9yIChnZW4gaW4gZ2VuZXJhKXsKICAgIENldGFjZWFfb2NjX2FnZ3JlZ19nZW4gPC0gcmJpbmQoQ2V0YWNlYV9vY2NfYWdncmVnX2dlbiwgc2FtcGxlX24oQ2V0YWNlYV9vY2NfZm9ybVtDZXRhY2VhX29jY19mb3JtJGdlbnVzPT1nZW4sXSwgc2l6ZSA9IDEpKQogIH0KfQoKIyBCcm93c2UgYWxsIGdlb3BsYXRlcwpnZW9wbGF0ZXMgPC0gbGV2ZWxzKGRyb3BsZXZlbHMoQ2V0YWNlYV9vY2NbQ2V0YWNlYV9vY2MkZm9ybWF0aW9uPT0iIixdJGdlb3BsYXRlKSkKZm9yIChncCBpbiBnZW9wbGF0ZXMpewogIENldGFjZWFfb2NjX2dwIDwtIENldGFjZWFfb2NjW0NldGFjZWFfb2NjJGZvcm1hdGlvbj09IiIgJiBDZXRhY2VhX29jYyRnZW9wbGF0ZT09Z3AsXQogIAogICMgQnJvd3NlIGFsbCBlYXJseSBzdHJhdGlncmFwaGljIGludGVydmFscwogIGVhcmx5X2ludGVydmFscyA8LSBsZXZlbHMoZHJvcGxldmVscyhDZXRhY2VhX29jY19ncCRlYXJseV9pbnRlcnZhbCkpCiAgZm9yIChlaSBpbiBlYXJseV9pbnRlcnZhbHMpewogICAgQ2V0YWNlYV9vY2NfZ3BfZWkgPC0gQ2V0YWNlYV9vY2NfZ3BbQ2V0YWNlYV9vY2NfZ3AkZWFybHlfaW50ZXJ2YWw9PWVpLF0KICAgIAogICAgIyBCcm93c2UgYWxsIGdlbmVyYSAmIHNhbXBsZSBvbmx5IDEgb2NjdXJyZW5jZQogICAgZ2VuZXJhIDwtIGxldmVscyhkcm9wbGV2ZWxzKENldGFjZWFfb2NjX2dwX2VpJGdlbnVzKSkKICAgIGZvciAoZ2VuIGluIGdlbmVyYSl7CiAgICAgIENldGFjZWFfb2NjX2FnZ3JlZ19nZW4gPC0gcmJpbmQoQ2V0YWNlYV9vY2NfYWdncmVnX2dlbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9uKENldGFjZWFfb2NjX2dwX2VpW0NldGFjZWFfb2NjX2dwX2VpJGdlbnVzPT1nZW4sXSwgc2l6ZSA9IDEpKQogICAgfQogIH0KfQoKZGF0YS5mcmFtZShDZXRhY2VhX29jYyA9IGMoZGltKENldGFjZWFfb2NjKVsxXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbShDZXRhY2VhX29jY1tDZXRhY2VhX29jYyRhY2NlcHRlZF9yYW5rICVpbiUgYygic3BlY2llcyIsICJnZW51cyIpLF0pWzFdKSwKICAgICAgICAgICBDZXRhY2VhX29jY19hZ2dyZWdfZ2VuID0gYyhkaW0oQ2V0YWNlYV9vY2NfYWdncmVnX2dlbilbMV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW0oQ2V0YWNlYV9vY2NfYWdncmVnX2dlbltDZXRhY2VhX29jY19hZ2dyZWdfZ2VuJGFjY2VwdGVkX3JhbmsgJWluJSBjKCJzcGVjaWVzIiwgImdlbnVzIiksXSlbMV0pLAogICAgICAgICAgIHJlbW92ZWQgPSBjKGRpbShDZXRhY2VhX29jYylbMV0tZGltKENldGFjZWFfb2NjX2FnZ3JlZ19nZW4pWzFdLAogICAgICAgICAgICAgICAgICAgICAgIGRpbShDZXRhY2VhX29jY1tDZXRhY2VhX29jYyRhY2NlcHRlZF9yYW5rICVpbiUgYygic3BlY2llcyIsICJnZW51cyIpLF0pWzFdLWRpbShDZXRhY2VhX29jY19hZ2dyZWdfZ2VuW0NldGFjZWFfb2NjX2FnZ3JlZ19nZW4kYWNjZXB0ZWRfcmFuayAlaW4lIGMoInNwZWNpZXMiLCAiZ2VudXMiKSxdKVsxXSksCiAgICAgICAgICAgcm93Lm5hbWVzID0gYygiTnVtYmVyIG9mIG9jY3VycmVuY2VzIiwgIk51bWJlciBvZiBvY2N1cnJlbmNlcyAoc3BlY2llcyBhbmQgZ2VuZXJhIG9ubHkpIikpCmBgYAoKTW9yZSBvY2N1cnJlbmNlcyByZW1haW4gYWZ0ZXIgYWdncmVnYXRpbmcgd2l0aCB0aGlzIG5ldyBtZXRob2QuIExldCdzIGNvbXBhcmUgYWdhaW4gd2l0aCB0aGUgdGhlb3JldGljYWwgZGlzdHJpYnV0aW9uIDoKCmBgYHtyIGZpZy5oZWlnaHQ9N30KIyBSZWNvdW50IHRoZSBudW1iZXIgb2Ygb2NjdXJyZW5jZXMgd2l0aCB0aGUgc2FtZSBnZW51cyBhZnRlciB0aGUgYWdncmVnYXRpb24KQ2V0YWNlYV9vY2MkZ2VudXNfY291bnQgPC0gc2FwcGx5KENldGFjZWFfb2NjJGdlbnVzLCBmdW5jdGlvbih4KXt0YWJsZShDZXRhY2VhX29jYyRnZW51cylbeF19KQpDZXRhY2VhX29jY19hZ2dyZWdfZ2VuJGdlbnVzX2NvdW50IDwtIHNhcHBseShDZXRhY2VhX29jY19hZ2dyZWdfZ2VuJGdlbnVzLCBmdW5jdGlvbih4KXt0YWJsZShDZXRhY2VhX29jY19hZ2dyZWdfZ2VuJGdlbnVzKVt4XX0pCgpvbWVnYSA8LSAwLjMKZ2VudXNfY291bnQgPC0gQ2V0YWNlYV9vY2NbQ2V0YWNlYV9vY2MkYWNjZXB0ZWRfcmFuayAlaW4lIGMoInNwZWNpZXMiLCAiZ2VudXMiKSxdJGdlbnVzX2NvdW50CmRlbnMgPC0gc2FwcGx5KDE6bWF4KGdlbnVzX2NvdW50KSwgZnVuY3Rpb24obil7IGV4cGVjdGVkX2Rpc3RyaWJ1dGlvbihuLCBvbWVnYSwgQ2V0YWNlYV9vY2NbQ2V0YWNlYV9vY2MkYWNjZXB0ZWRfcmFuayAlaW4lIGMoInNwZWNpZXMiLCAiZ2VudXMiKSxdJGFnZV9jb21iaW5lZF9yYW5nZSkkdmFsdWUgfSkKZ2VudXNfY291bnRfY2F0ZWdvcmllcyA8LSB0YWJsZShnZW51c19jb3VudCkvYXMubnVtZXJpYyhuYW1lcyh0YWJsZShnZW51c19jb3VudCkpKSAgIyBOdW1iZXIgb2YgY2F0ZWdvcmllcyB3aXRoIDEsIDIsIDMsIC4uLiBvY2N1cnJlbmNlcyBvZiB0aGUgc2FtZSBnZW51cwoKIyBDb21wYXJlIHRoZSBpbml0aWFsIG9ic2VydmVkIGRpc3RyaWJ1dGlvbiB3aXRoIHRoZSB0aGVvcmV0aWNhbCBjdXJ2ZQpnZ3Bsb3QoQ2V0YWNlYV9vY2NbQ2V0YWNlYV9vY2MkYWNjZXB0ZWRfcmFuayAlaW4lIGMoInNwZWNpZXMiLCAiZ2VudXMiKSxdLCAKICAgICAgIGFlcyh4PWdlbnVzX2NvdW50LCAKICAgICAgICAgICB5PWdlbnVzX2NvdW50X2NhdGVnb3JpZXNbYXMuZmFjdG9yKGdlbnVzX2NvdW50KV0sIAogICAgICAgICAgIGZpbGw9YWNjZXB0ZWRfcmFuaykpICsKICBnZW9tX3BvaW50KCkgKwogIAogIGFubm90YXRlKCJsaW5lIiwgeCA9IDE6bWF4KGdlbnVzX2NvdW50KSwgeT0gZGVucwogICAgKm1heCgodGFibGUoZ2VudXNfY291bnQpL2FzLm51bWVyaWMobmFtZXModGFibGUoZ2VudXNfY291bnQpKSkpW2FzLmZhY3RvcihnZW51c19jb3VudCldKSAvbWF4KGRlbnMpKSsKICAKICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJOdW1iZXIgb2Ygb2NjdXJyZW5jZXMgYnkgZ2VudXMiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKHRyYW5zID0gImxvZzEwIiwgbmFtZSA9ICJOdW1iZXIgb2YgY29ycmVzcG9uZGluZyBnZW5lcmEgKGxvZy1zY2FsZSkiKSArCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lPSJPYnNlcnZlZCBkaXN0cmlidXRpb24iKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCkpICsKICBnZ3RpdGxlKCJDb21wYXJpc29uIGJldHdlZW4gZXhwZWN0ZWQgYW5kIG9ic2VydmVkIGRpc3RyaWJ1dGlvbnMgb2YgbnVtYmVyIG9mIG9jY3VycmVuY2VzIikKCmdlbnVzX2NvdW50X2FnZ3JlZyA8LSBDZXRhY2VhX29jY19hZ2dyZWdfZ2VuW0NldGFjZWFfb2NjX2FnZ3JlZ19nZW4kYWNjZXB0ZWRfcmFuayAlaW4lIGMoInNwZWNpZXMiLCAiZ2VudXMiKSxdJGdlbnVzX2NvdW50CmRlbnNfYWdncmVnIDwtIHNhcHBseSgxOm1heChnZW51c19jb3VudF9hZ2dyZWcpLCBmdW5jdGlvbihuKXsKICAgICBleHBlY3RlZF9kaXN0cmlidXRpb24obiwgb21lZ2EsIENldGFjZWFfb2NjX2FnZ3JlZ19nZW5bQ2V0YWNlYV9vY2NfYWdncmVnX2dlbiRhY2NlcHRlZF9yYW5rICVpbiUgYygic3BlY2llcyIsICJnZW51cyIpLF0kYWdlX2NvbWJpbmVkX3JhbmdlKSR2YWx1ZQogICAgfSkKCiMgTnVtYmVyIG9mIGNhdGVnb3JpZXMgd2l0aCAxLCAyLCAzLCAuLi4gb2NjdXJyZW5jZXMgb2YgdGhlIHNhbWUgZ2VudXMKZ2VudXNfY291bnRfY2F0ZWdvcmllc19hZ2dyZWcgPC0gdGFibGUoZ2VudXNfY291bnRfYWdncmVnKS9hcy5udW1lcmljKG5hbWVzKHRhYmxlKGdlbnVzX2NvdW50X2FnZ3JlZykpKQoKIyBOdW1iZXIgb2Ygb2NjdXJyZW5jZXMgYnkgY2F0ZWdvcnkKQ2V0YWNlYV9vY2NfYWdncmVnX2dlbiRnZW51c19jYXRlZ29yaWVzX2NvdW50IDwtIGFzLm51bWVyaWMoZ2VudXNfY291bnRfY2F0ZWdvcmllc19hZ2dyZWdbYXMuZmFjdG9yKENldGFjZWFfb2NjX2FnZ3JlZ19nZW4kZ2VudXNfY291bnQpXSkKCiMgQ29tcGFyZSB0aGUgY29ycmVjdGVkIG9ic2VydmVkIGRpc3RyaWJ1dGlvbiB3aXRoIHRoZSB0aGVvcmV0aWNhbCBjdXJ2ZQpnZ3Bsb3QoQ2V0YWNlYV9vY2NfYWdncmVnX2dlbltDZXRhY2VhX29jY19hZ2dyZWdfZ2VuJGFjY2VwdGVkX3JhbmsgJWluJSBjKCJzcGVjaWVzIiwgImdlbnVzIiksXSwgCiAgICAgICBhZXMoeD1nZW51c19jb3VudCwKICAgICAgICAgICB5PWdlbnVzX2NhdGVnb3JpZXNfY291bnQsCiAgICAgICAgICAgc2l6ZT1nZW51c19jYXRlZ29yaWVzX2NvdW50KSkgKwogIGdlb21fcG9pbnQoKSArCiAgCiAgYW5ub3RhdGUoImxpbmUiLCB4ID0gMTptYXgoZ2VudXNfY291bnRfYWdncmVnKSwgeT0gZGVuc19hZ2dyZWcKICAgICptYXgoKHRhYmxlKGdlbnVzX2NvdW50X2FnZ3JlZykvYXMubnVtZXJpYyhuYW1lcyh0YWJsZShnZW51c19jb3VudF9hZ2dyZWcpKSkpW2FzLmZhY3RvcihnZW51c19jb3VudF9hZ2dyZWcpXSkgL21heChkZW5zX2FnZ3JlZykpICsKICAKICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJOdW1iZXIgb2Ygb2NjdXJyZW5jZXMgYnkgZ2VudXMiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKHRyYW5zID0gImxvZzEwIiwgbmFtZSA9ICJOdW1iZXIgb2YgY29ycmVzcG9uZGluZyBnZW5lcmEgKGxvZy1zY2FsZSkiKSArCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lPSJPYnNlcnZlZCBkaXN0cmlidXRpb24iKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCkpICsKICBnZ3RpdGxlKCJDb21wYXJpc29uIGJldHdlZW4gZXhwZWN0ZWQgYW5kIG9ic2VydmVkIGRpc3RyaWJ1dGlvbnMgb2YgbnVtYmVyIG9mIG9jY3VycmVuY2VzLCBhZnRlciBhZ2dyZWdhdGluZyBpbiBnZW9wbGF0ZXMiKQoKZ2VudXNfY291bnRfYWdncmVnIDwtIENldGFjZWFfb2NjX2FnZ3JlZ19nZW5bQ2V0YWNlYV9vY2NfYWdncmVnX2dlbiRhY2NlcHRlZF9yYW5rICVpbiUgYygic3BlY2llcyIsICJnZW51cyIpLF0kZ2VudXNfY291bnQKZGVuc19hZ2dyZWcgPC0gc2FwcGx5KDE6bWF4KGdlbnVzX2NvdW50X2FnZ3JlZyksIGZ1bmN0aW9uKG4pewogICAgIGV4cGVjdGVkX2Rpc3RyaWJ1dGlvbihuLCBvbWVnYSwgQ2V0YWNlYV9vY2NfYWdncmVnX2dlbltDZXRhY2VhX29jY19hZ2dyZWdfZ2VuJGFjY2VwdGVkX3JhbmsgJWluJSBjKCJzcGVjaWVzIiwgImdlbnVzIiksXSRhZ2VfY29tYmluZWRfcmFuZ2UpJHZhbHVlCiAgICB9KQpnZW51c19jb3VudF9jYXRlZ29yaWVzX2FnZ3JlZyA8LSB0YWJsZShnZW51c19jb3VudF9hZ2dyZWcpL2FzLm51bWVyaWMobmFtZXModGFibGUoZ2VudXNfY291bnRfYWdncmVnKSkpICAjIE51bWJlciBvZiBjYXRlZ29yaWVzIHdpdGggMSwgMiwgMywgLi4uIG9jY3VycmVuY2VzIG9mIHRoZSBzYW1lIGdlbnVzCmBgYAoKJFx0byQgVGhlIGNvcnJlc3BvbmRhbmNlIGlzIG11Y2ggbGVzcyBpbXByb3ZlZCB0aGFuIHdpdGggc3BlY2llcyBhZ2dyZWdhdGlvbiBiZWNhdXNlIHNvbWUgZ2VuZXJhIGhhdmUgYSBsb3Qgb2Ygb2NjdXJyZW5jZXMgZHVlIHRvIHRoZWlyIGhpZ2ggbnVtYmVyIG9mIHNwZWNpZXMgc3BlY2llcyA6CgpgYGB7cn0KdGFibGUoZHJvcGxldmVscyhDZXRhY2VhX29jY19hZ2dyZWdfZ2VuWyhDZXRhY2VhX29jY19hZ2dyZWdfZ2VuJGFjY2VwdGVkX3JhbmsgJWluJSBjKCJzcGVjaWVzIiwgImdlbnVzIikpICYgKENldGFjZWFfb2NjX2FnZ3JlZ19nZW4kZ2VudXNfY291bnQ+MjUpLF0kZ2VudXMpKQpgYGAKCmBgYHtyIGZpZy5oZWlnaHQ9Nn0KY29uZGl0aW9ucyA8LSBDZXRhY2VhX29jYyRhY2NlcHRlZF9yYW5rICVpbiUgYygic3BlY2llcyIsICJnZW51cyIpCgpwMSA8LSBnZ3Bsb3QoQ2V0YWNlYV9vY2NbY29uZGl0aW9ucyxdLCBhZXMoeD0tYWdlX3J1bmlmKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC41LCBhbHBoYT0wLjUsIGZpbGw9TkEsIGNvbD0icmVkIikgKwogIHhsaW0oLW1heChDZXRhY2VhX29jY1tjb25kaXRpb25zLF0kYWdlX3J1bmlmKS0xLCAxKSArCiAgeWxpbSgwLCA4MCkgKwogIHRoZW1lX3ZvaWQoKQoKcDIgPC0gZ2dwbG90KENldGFjZWFfb2NjX3NhbXBsZWQsIGFlcyh4PS1hZ2VfcnVuaWYpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjUsIGFscGhhPTAuNSwgZmlsbD0iYmx1ZSIpICsKICB4bGltKC1tYXgoQ2V0YWNlYV9vY2NbY29uZGl0aW9ucyxdJGFnZV9ydW5pZiktMSwgMSkgKwogIHlsaW0oMCwgODApICsKICB0aGVtZV92b2lkKCkKCnAzIDwtIGdncGxvdChDZXRhY2VhX29jY19hZ2dyZWdfZ2VuW0NldGFjZWFfb2NjX2FnZ3JlZ19nZW4kYWNjZXB0ZWRfcmFuayAlaW4lIGMoInNwZWNpZXMiLCAiZ2VudXMiKSxdLCBhZXMoeD0tYWdlX3J1bmlmKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC41LCBhbHBoYT0wLjUsIGZpbGw9ImdyZWVuIikgKwogIHhsaW0oLW1heChDZXRhY2VhX29jY1tjb25kaXRpb25zLF0kYWdlX3J1bmlmKS0xLCAxKSArCiAgeWxpbSgwLCA4MCkgKwogIHRoZW1lX3ZvaWQoKQoKcDEgKyBhbm5vdGF0aW9uX2N1c3RvbShnZ3Bsb3RHcm9iKHAyKSkgKyBnZ3RpdGxlKCJJbml0aWFsIG9jY3VycmVuY2VzIGRpc3RyaWJ1dGlvbiAocmVkKSBhbmQgY29tcGFyaXNvbiBhZnRlciBzdWItc2FtcGxpbmcgKGJsdWUpIikKCnAxICsgYW5ub3RhdGlvbl9jdXN0b20oZ2dwbG90R3JvYihwMykpICsgZ2d0aXRsZSgiSW5pdGlhbCBvY2N1cnJlbmNlcyBkaXN0cmlidXRpb24gKHJlZCkgYW5kIGNvbXBhcmlzb24gYWZ0ZXIgYWdncmVnYXRpbmcgaW4gZ2VvcGxhdGVzIChncmVlbikiKQoKcDEgKyBhbm5vdGF0aW9uX2N1c3RvbShnZ3Bsb3RHcm9iKHAyKSkgKyBhbm5vdGF0aW9uX2N1c3RvbShnZ3Bsb3RHcm9iKHAzKSkgKyBnZ3RpdGxlKCJJbml0aWFsIG9jY3VycmVuY2VzIGRpc3RyaWJ1dGlvbiAocmVkKSBhbmQgY29tcGFyaXNvbiBhZnRlciBzdWItc2FtcGxpbmcgKGJsdWUpIG9yIGFnZ3JlZ2F0aW5nIGluIGdlb3BsYXRlcyAoZ3JlZW4pIikKYGBgCgokXHRvJCBEZWxpbWl0aW5nIGJ5IGdlb2xvZ2ljYWwgcGxhdGVzICgrIGFnZSkgaW5zdGVhZCBvZiBjb3VudHJpZXMgKCsgYWdlKSBsZWFkcyB0byBzaW1pbGFyIGRpc3RyaWJ1dGlvbnMsIHdpdGggYSBiaXQgbW9yZSBvY2N1cnJlbmNlcywgc28gd2Ugd2lsbCBrZWVwIGl0LgoKYGBge3J9CndyaXRlLnRhYmxlKENldGFjZWFfb2NjX2FnZ3JlZ19nZW5bQ2V0YWNlYV9vY2NfYWdncmVnX2dlbiRhY2NlcHRlZF9yYW5rICVpbiUgYygic3BlY2llcyIsICJnZW51cyIpLCBjKCJtaW5fbWEiLCAibWF4X21hIildLAogICAgICAgICAgICBmaWxlPSJkYXRhLWNldGFjZWFucy9DZXRhY2VhX29jY3VycmVuY2VzX21pbl9tYXhfYWdlX2dlbmVyYV9jb3JyZWN0ZWQuY3N2Iiwgc2VwPSIsIiwgcm93Lm5hbWVzPUZBTFNFLCBjb2wubmFtZXM9RkFMU0UpCmBgYAoKIyBDb25jbHVzaW9ucwoKQWNoaWV2ZW1lbnRzIDoKCiAgLSBJdCBzZWVtcyBwb3NzaWJsZSB0byBhZGVxdWF0ZWx5IHJlZHVjZSB0aGUgYWJ1bmRhbmNlIGJpYXMgYnkgc3Vic2FtcGxpbmcgdGhlIG1vc3QgY29uY2VudHJhdGVkIGludGVydmFscyAkXHRvJCAqKnNwZWNpZXMgb25seSoqCiAgLSBVc2luZyBjb21iaW5lZCByYW5nZXMgYnkgc3BlY2llcyBhcHBlYXJzIHRvIGJlIG1vcmUgcm9idXN0ICRcdG8kICoqdG8gYmUgY29uZmlybWVkKioKICAtIFZlcnkgcmVjZW50IHNhbXBsZXMgbWF5IGhhdmUgYmVlbiBkYXRlZCB3aXRoIGEgbW9yZSBwcmVjaXNlIG1ldGhvZCBhbmQgY29udGFpbiBtdWNoIG1vcmUgZm9zc2lscywgc28gdGhleSBzaG91bGQgYmUgcmVtb3ZlZCBvciB0cmVhdGVkIHNlcGFyYXRhZGVseSAkXHRvJCAqKmFkZGl0aW9uYWwgaW5mb3JtYXRpb24gbmVlZGVkKioKCk9wZW4gcXVlc3Rpb25zIDoKCiAgLSBXaGF0IGFib3V0IG90aGVyIGFjY2VwdGVkIHJhbmtzID8KICAgIDEuIFRoZSBwcm9ibGVtIGlzIHRoYXQgZGlmZmVyZW5jZXMgaW4gdGhlIG51bWJlciBvZiBvY2N1cnJlbmNlcyBhdCBoaWdoZXIgcmFua3MgY291bGQgYmUgZHVlIHRvIGRpZmZlcmVuY2VzIGluIGluZGl2aWR1YWwgYWJ1bmRhbmNlcyBpbnNpZGUgc3BlY2llcyBvciBkdWUgdG8gZGlmZmVyZW5jZXMgaW4gdGhlIG51bWJlciBvZiBzcGVjaWVzIGluc2lkZSB0aGF0IGdyb3VwLgogICAgMi4gQSBzb2x1dGlvbiBjb3VsZCBiZSB0byBsb29rIGF0IHRoZSBudW1iZXIgb2Ygc3BlY2llcyBieSBncm91cCBiYXNlZCBvbiB0aGUgaW5kaWNhdGVkIHNwZWNpZXMsIGFuZCBpbmNsdWRlIGl0IGluIHRoZSBiaWFzIGNvcnJlY3Rpb24gOiBob21vZ2VuZWl6aW5nIHRoZSAqbnVtYmVyIG9mIG9jY3VycmVuY2VzIC8gdGltZSB1bml0IC8gbnVtYmVyIHNmIHNwZWNpZXMgaW4gdGhlIGdyb3VwKiAkXHRvJCAqKmFkZGl0aW9uYWwgZGF0YSByZXF1aXJlZCoqIChyYW5rcyBjbGFzc2lmaWNhdGlvbikKICAtIFdoeSBkbyBtb3N0IG9jY3VycmVuY2VzIG1pc3MgYSBsYXRlIHN0cmF0aWdyYXBoaWMgbGltaXQgPwogIC0gU29tZSBvY2N1cnJlbmNlcyBoYXZlIHZlcnkgaHVnZSB0aW1lIGludGVydmFscyAkXHRvJCAqKldhcyBpcyBhIGdvb2QgaWRlYSB0byByZW1vdmUgdGhvc2UgPjEwTXkgPyBTaG91bGQgd2UgcmVtb3ZlIG1vcmUgb2YgdGhlbSAoPjVNeSkgPyoqCgoKICAgIAogICAg